标签:
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6842 Accepted Submission(s):
4144
[定理1]:对于任何一个S态,总能从一堆火柴中取出若干个使之成为T态。
证明:
若有n堆火柴,每堆火柴有A(i)根火柴数,那么既然现在处于S态,
c = A(1) xor A(2) xor … xor A(n) > 0;
把c表示成二进制,记它的二进制数的最高位为第p位,则必然存在一个A(t),它二进制的第p位也是1。(否则,若所有的A(i)的第p位都是0,这与c的第p位就也为0矛盾)。
那么我们把x = A(t) xor c,则得到x < A(t).这是因为既然A(t)的第p位与c的第p位同为1,那么x的第p位变为0,而高于p的位并没有改变。所以x < A(t).而
A(1) xor A(2) xor … xor x xor … xor A(n)
= A(1) xor A(2) xor … xor A(t) xor c xor … xor A(n)
= A(1) xor A(2) xor… xor A(n) xor A(1) xor A(2) xor … xor A(n)
= 0
这就是说从A(t)堆中取出 A(t) - x 根火柴后状态就会从S态变为T态。证毕
#include<iostream> #include<cstdio> #include<cstring> #include<stdlib.h> #include<algorithm> #include<cmath> using namespace std; int N[105]; int main() { int m; while(scanf("%d",&m)!=EOF&&m) { int k=0; for(int i=0; i<m; i++) { scanf("%d",&N[i]); k^=N[i]; } if(k==0) printf("0\n"); else { int pos=0; for(int i=0;i<=30;i++) { int tmp=(1<<i); if((tmp&k)>0) pos=i; } //cout<<pos<<endl; int res=0; for(int i=0;i<m;i++) if((N[i]&(1<<pos))>0&&(N[i]^k)<N[i]) res++; printf("%d\n",res); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/jasonlixuetao/p/5899540.html