CF662A Gambling Nim

Solution

\(\mathrm{Nim}\) 游戏结论,对于一种情况先手必败,当且仅当:

\[\bigg(\bigoplus_{i=1}^k a_{\mathrm{pos}_i}\bigg) \oplus \bigg( \bigoplus_{i=k+1}^{n} b_{\mathrm{pos}_i }\bigg)=0 \]

其中 \(k\) 表示选择正面的数量,\(\mathrm{pos}_i\) 表示选择的位置。

该条件中的位置以及选择方案都是不确定的。考虑将等式两边同时异或 \(\bigoplus_{i=1}^n a_i\)

\[\bigg(\bigoplus_{i=k+1}^{n} a_{\mathrm{pos}_i } \oplus b_{\mathrm{pos}_i }\bigg)=\bigoplus_{i=1}^n a_i \]

\(c_i=a_i \oplus b_i\)。于是问题转化成了选出若干个位置 \(\mathrm{pos}_i\) 使得这些位置的 \(c_i\) 的异或和为 \(\bigoplus_{i=1}^n a_i\)

考虑将所有的 \(c_i\) 丢进线性基。若无法表示 \(\bigoplus_{i=1}^n a_i\),先手必胜的概率为 \(1\)。否则令 \(\mathrm{siz}\) 表示线性基的大小,先手必胜的概率为 \(1-\frac{2^{n-\mathrm{siz}}}{2^{n}}=\frac{2^{\mathrm{siz}}-1}{2^{\mathrm{siz}}}\)

Code

/* ChongYun */
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
using namespace std;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int n,sum=0;
struct Node{
    int p[63],siz=0;
    int size(){ return siz; }
    int insert(int x){
        for(int i=62;i>=0;i--){
            if(!(x>>i)) continue;
            if(!p[i]){
                p[i]=x;
                ++siz;
                return 1;
            }
            x^=p[i];
        }
        return 0;
    }
}S;
signed main(){
    n=read();
    for(int i=1;i<=n;i++){
        int a=read(),b=read();
        sum^=a,S.insert(a^b);
    }
    if(S.insert(sum)) printf("1/1\n");
    else printf("%lld/%lld\n",(1ll<<S.size())-1,(1ll<<S.size()));
    return 0;
}
posted @ 2025-05-31 11:03  HAM_qwq  阅读(12)  评论(0)    收藏  举报