AtCoder Grand Contest 045 A - Xor Battle

 

 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\n", flag);
    }
    return 0;
}

 

posted @ 2020-09-09 00:19  摸鱼选手LLF  阅读(192)  评论(0)    收藏  举报