专栏文章
题解:AT_agc045_a [AGC045A] Xor Battle
AT_agc045_a题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip4y8mx
- 此快照首次捕获于
- 2025/12/03 06:14 3 个月前
- 此快照最后确认于
- 2025/12/03 06:14 3 个月前
由于是线性基专题,于是直接对整个序列套线性基想了半天,发现不可做。
于是还是要从简单的情况想起。
考虑已经进行完了 次操作,当前的数是 ,
- 若 , 必胜。
- 若 ,当且仅当 或 , 必胜。
我们发现维护 的必胜集合似乎比 容易一些。
设 表示进行完 轮后,能使 必胜的 的取值集合,
,
,
直接用
set 维护会 TLE,考虑优化。考虑一个 ,如果 全部都是 ,那么 其实就是 的异或生成空间。
考虑倒数第一个 的位置,若 ,则整个 都是满足条件的,可以直接继承过来;若 ,那么不存在 ,使得 ,于是这时候 ,直接判 必胜即可。
这样我们就处理了 的情况,
倒着扫一遍,用线性基维护即可。
CPP#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using UI = unsigned int;
using ULL = unsigned long long;
using DB = double;
using LDB = long double;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
#define CP(x) complex<x>
#define fst first
#define snd second
#define popcnt(i) __builtin_popcount(i)
const int N = 2e2 + 5;
int n;
string s;
LL a[N];
struct Basis {
int n;
LL b[65];
void init(int _n) {
n = _n;
for (int i = 0; i <= n; i++) {
b[i] = 0;
}
}
void insert(LL x) {
for (int i = n; i >= 0; i--) {
if ((x >> i) & 1) {
if (!b[i]) {
b[i] = x;
return;
}
x ^= b[i];
}
}
}
bool find(LL x) {
for (int i = n; i >= 0; i--) {
if ((x >> i) & 1) {
if (!b[i]) {
return false;
}
x ^= b[i];
}
}
return true;
}
} B;
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cin >> s;
s = ' ' + s;
B.init(60);
for (int i = n; i >= 1; i--) {
if (s[i] == '0') {
B.insert(a[i]);
} else if (!B.find(a[i])) {
cout << 1 << '\n';
return;
}
}
cout << 0 << '\n';
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--) solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...