专栏文章

题解: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 个月前
查看原文
由于是线性基专题,于是直接对整个序列套线性基想了半天,发现不可做。
于是还是要从简单的情况想起。
考虑已经进行完了 n1n-1 次操作,当前的数是 xx
  1. sn=1s_n=111 必胜。
  2. sn=0s_n=0,当且仅当 x=0x=0x=anx=a_n00 必胜。
我们发现维护 00 的必胜集合似乎比 11 容易一些。
FiF_i 表示进行完 i1i-1 轮后,能使 00 必胜的 xx 的取值集合,
Fn={{0,an}sn=0sn=1F_n=\begin{cases}\{0,a_n\} & s_n=0 \\ \varnothing & s_n=1\end{cases}
Fi={{xxFi+1xaiFi+1}sn=0{xxFi+1xaiFi+1}sn=1F_i=\begin{cases}\{x\mid x\in F_{i+1} \vee x\oplus a_i \in F_{i+1}\} & s_n=0 \\ \{x\mid x\in F_{i+1} \wedge x\oplus a_i \in F_{i+1}\} & s_n=1\end{cases}
直接用 set 维护会 TLE,考虑优化。
考虑一个 FiF_i,如果 sisns_i \cdots s_n 全部都是 00,那么 FiF_i 其实就是 aiana_i \cdots a_n 的异或生成空间。
考虑倒数第一个 si=1s_i=1 的位置,若 aiFi+1a_i\in F_{i+1},则整个 Fi+1F_{i+1} 都是满足条件的,可以直接继承过来;若 aiFi+1a_i\notin F_{i+1},那么不存在 xFi+1x\in F_{i+1},使得 xaiFi+1x\oplus a_i\in F_{i+1},于是这时候 Fi=F_i=\varnothing,直接判 11 必胜即可。
这样我们就处理了 si=1s_i=1 的情况,
倒着扫一遍,用线性基维护即可。
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 条评论,欢迎与作者交流。

正在加载评论...