P2197 nim遊戲(nim博弈)

題目傳送門

題意: 有n堆石子,每一堆有a[i]個,兩個人輪流取石子,每次只可以在一堆中取,可以取完但是不能不取,最後無石可取的人失敗,假設雙方都足夠聰明,問你先手有沒有必勝策略?

結論: 當且僅當 a[1] xor a[2] xor a[3] … a[n-1] xor a[n]==0時先手敗。

證明: 一、最開始n堆石子都是0個的情況,先手敗。
二、有n是偶數且所有堆石子相同,先手敗(後手只需要每次跟先手拿一樣的數目)。
三、其他異或和爲0的情況。這時候,假設我們先手拿了石子打破了異或和爲0的情況,當前異或和爲x,假設x的二進制最高位是第k位,那麼必然至少有一個a[i]的第k位是1,我們就一定可以通過拿第i堆,讓剩下的異或和爲0。

代碼:

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-7;
const double PI=acos(-1);
int a[N],b[N];
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int res=0;
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            res^=x;
        }
        if(res==0)
            cout<<"No"<<endl;
        else
            cout<<"Yes"<<endl;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章