【BZOJ1299】巧克力棒(Nim游戏,SG函数)
题意:TBL和X用巧克力棒玩游戏。每次一人可以从盒子里取出若干条巧克力棒,或是将一根取出的巧克力棒吃掉正整数长度。
TBL先手两人轮流,无法操作的人输。
他们以最佳策略一共进行了10轮(每次一盒)。你能预测胜负吗?
如果TBL胜则输出”NO”,否则输出”YES”
n<=14,a[i]<=1e9
思路:一个结论:Nim游戏中一个xor和不为0(先手必胜)的状态一定可以通过1步转化为xor和为0(先手必败)的状态
所以先手第一步只需要取出一个xor和为0的最长子序列
若后手选择加入新巧克力棒,先手可以通过1步将已经加入的Nim游戏变为xor和为0的局面
若后手选择取已经加入的部分,先手依然可以通过1步将后手行动过的局面的xor和变为0
所以只需要判断初始局面下存不存在xor和为0的子序列
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 typedef long long ll; 7 using namespace std; 8 #define N 210000 9 #define oo 10000000 10 #define MOD 1000000007 11 12 int a[N],b[N],f[N]; 13 14 int lowbit(int x) 15 { 16 return x&(-x); 17 } 18 19 int main() 20 { 21 for(int v=1;v<=10;v++) 22 { 23 int n; 24 scanf("%d",&n); 25 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 26 int x=1; 27 for(int i=1;i<=n;i++) 28 { 29 b[x]=i; 30 x<<=1; 31 } 32 f[0]=0; 33 for(int i=1;i<=(1<<n)-1;i++) f[i]=f[i^lowbit(i)]^a[b[lowbit(i)]]; 34 int ans=0; 35 for(int i=1;i<=(1<<n)-1;i++) 36 if(!f[i]) ans=1; 37 if(ans) printf("NO\n"); 38 else printf("YES\n"); 39 } 40 return 0; 41 } 42
null