Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3142 Accepted Submission(s): 1821
一.
如果a1^a2^a3^...^an=0 ( 即 : nim-sum=0 ) , 说明先手没有必赢策略, 方法数肯定为 0;
二.
假设先手的人有必赢策略。
问题则转化为=>在任意一堆拿任意K张牌,并且剩下所有堆的nim-sum=0(P-position)的方案总数。
1. 现在我们先看一个例子(5,7,9),并假设从第一堆取任意K张牌。
排除第一堆牌的nim-sum为 7^9=14
0111
^1001
-------
1110
如果要使所有堆的nim-sum=0成立,则第一堆取掉K张以后必定为1110,因为X^X=0。
所以要观察 5-k=14 k>0 成立,此例子(在第一堆取任意K张牌)明显的不成立。但并不代表在第二或第三堆取任意K张牌的解不成立。
2. 现在看第二个例子(15,7,9),并假设从第一堆取任意K张牌。
排队第一堆牌的nim-sum为7^9=14,和第一个例子相同,所以问题变为观察 15-k=14 k>0 是否成立。
当然这个例子是成立的。
三.
总结得出:
在任意一堆拿任意K张牌,并且所有堆的nim-sum=0 成立的条件为:排除取掉K张牌的那一堆的nim-sum必须少于该堆牌上的数量(例子二),否则不能在此堆上取任意K张牌使所有堆的nim-sum=0成立(例子一)。
故总方案数为 ( 在任意一堆拿任意K张牌,并且所有堆的nim-sum=0 成立 ) 的总数。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; int n,a[110]; int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&n) && n){ int ans=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); ans^=a[i]; } if(ans==0){ puts("0"); continue; } int cnt=0; for(int i=0;i<n;i++) if((a[i]^ans)<=a[i]) //这样保证从该堆中能取到合法的数目(即不超过该堆扑克牌的总数) cnt++; printf("%d\n",cnt); } return 0; }