zoukankan      html  css  js  c++  java
  • CF662A Gambling Nim 线性基

    挺好的一道题.   

    判断先手必胜即判断所有数异或值是否为 0.   

    直接判断的话不好做,不妨先强制所有数选 a,然后再看有几种方案使得选一些 b 让序列异或值为 0.   

    假如想让位置 i 从 a->b,要异或上 $a_{i}$ xor $b_{i}$.  

    那么,就先求出所有 $a_{i}$ 的异或和 sum,然后将 $a_{i}$ xor $b_{i}$ 扔到线性基里,看看有几种方案使得线性基里异或和等于 sum.            

    根据线性基的相关定理,每种异或和出现次数都是相同,所有输出 $2^{size}-1/2^{size}$ 即可.  

    code:   

    #include <cstdio> 
    #include <algorithm>   
    #define N 64   
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin)   
    using namespace std; 
    ll p[63];       
    int cnt=0; 
    int ins(ll x) {  
        for(int i=62;i>=0;--i) {  
            if(x&(1ll<<i)) {   
                if(p[i]) 
                    x^=p[i];    
                else {  
                    p[i]=x;   
                    ++cnt;  
                    return 1; 
                }
            }     
        }  
        return 0; 
    }
    int main() {  
        // setIO("input"); 
        int n;  
        scanf("%d",&n);  
        ll sum=0;
        for(int i=1;i<=n;++i) {  
            ll a,b;     
            scanf("%lld%lld",&a,&b); 
            sum^=a;  
            ins(a^b); 
        }   
        if(ins(sum)) printf("1/1
    ");   
        else { 
            printf("%lld/%lld
    ",(1ll<<cnt)-1,1ll<<cnt);     
        }
        return 0; 
    }
    

      

  • 相关阅读:
    day09 文件操作
    深信服二面
    test1
    视频测试
    通过独立按键控制LED灯
    第一个LED灯
    为什么我的递归调用次数和书上的不一样?
    函数指针数组
    虚拟内存
    单元测试
  • 原文地址:https://www.cnblogs.com/guangheli/p/13277956.html
Copyright © 2011-2022 走看看