T组样例
题意
博弈游戏 一开始有个value是0
第一个人的目标是让value保持0
第二个人是让value不为0
给一个长度为N数组
然后给一个长度为N字符串
0代表第一个人可以选择此数进行异或,也可以什么都不干
1代表第二个人
题解: 显然 第二个人没动手之前,第一个人不动
所以倒着来一次线性基就行了(后缀)
一旦第一个人表示不出来后面的数
就GG
第一次做的时候蒙蒙糊糊的就过了
隔了好几天,写这个博客的时候,回来想了一次没想明白,然后开始质疑自己的代码,2333,然后后来是这样理解
两个集合如果值域相等(异或的值域) ,要如何判断呢?
只需要把一个集合拉成线性基,然后把另一个集合的元素插入,只要每个元素都能被表示,那么两个集合的异或值域相等
所以我们倒着来 依次将元素插入线性基就可以了
代码:线性基板子
#include<bits/stdc++.h> #define pb push_back #define fi first #define se second #define io std::ios::sync_with_stdio(false) using namespace std; typedef long long ll; typedef pair<ll,ll> pii; const double pi=acos(-1); const ll P = 998244353, INF = 0x3f3f3f3f; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll qpow(ll a,ll n){ll r=1%P;for (a%=P; n; a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;} const double eps=1e-5; ll lcm(ll a,ll b){return a*b/gcd(a,b);}; const int maxn = 200 + 10; ll a[maxn]; const int L = 63; ll d[L]; bool add(ll x){ for(int i = L - 1; i >= 0; i--) if(x & 1ll << i){ if(d[i] == -1){d[i] = x; return true;} x ^= d[i]; } return false; } int main(){ // Fast; int t; scanf("%d", &t); while(t--){ memset(d, -1, sizeof d); int n; scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%lld", a + i); char s[maxn]; scanf("%s", s); int flag = 0; for(int i = n - 1; i >= 0; i--){ if(add(a[i]) && s[i] == '1'){ flag = 1; break; } } printf("%d ", flag); } return 0; }