这是一道关于博弈的题目,这一题挺不错的,如果知道了nim游戏异或的道理,这一题是比较好写的。
Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异 或(xor)运算。
•对于某个局面(a1,a2,...,an),若a1^a2^...^an==k(k>0)
•一定存在某个合法的移动,将ai改变成ai'后满足 a1^a2^...^ai'^...^an=0
•一定存在某个ai,它的二进制表示在k的最高位上是1 (ai^k<ai 成立)
•将ai改变成ai'=ai^k a1^a2^...^ai'^...^an=a1^a2^...^an^k=0
有了这个,我们就可以直接找含有最高位为1的值就可以了,但是一定要注意,找到最高位为1后还要判断ai^k<ai,因为有可能有K值的最高位并不是在ai中,譬如k=1,10^K>10.我就是因为之前没有考虑这个,很悲剧的WA了两次(其中有一次是范围有问题我找出来后还是WA^_^)
View Code
1 #include <cstdio>
2 #include <algorithm>
3 using namespace std;
4
5 int heap[120];
6
7 int main()
8 {
9 int m;
10 while(scanf("%d",&m) == 1)
11 {
12 if(!m)
13 break;
14 int i;
15 int sum = 0;
16 for(i = 0;i < m;i ++)
17 {
18 scanf("%d",&heap[i]);
19 sum ^= heap[i];
20 }
21 if(sum == 0)
22 {
23 printf("0\n");
24 continue;
25 }
26 sort(heap,heap + m);
27 int k = 0;
28 int n = sum;//记录sum的值以备后用
29 while(sum)
30 {
31 sum>>=1;
32 k ++;//记录sum的位数
33 }
34 int t;
35 t = 1 << (k - 1);//计算最高位为1的最小值
36 //printf("k:%d;t:%d\n",k,t);
37 k = 0;
38 for(i = m-1;i >= 0;i --)
39 {
40 if(heap[i] < t)
41 break;
42 if(heap[i] >= t&&(heap[i]^n )< heap[i])//一定要用(heap[i]^n )< heap[i],并注意异或的优先级
43 k ++;
44 }
45 printf("%d\n",k);
46 }
47 return 0;
48 }