Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8823 | Accepted: 5095 |
Description
Input
Output
Sample Input
2 45 45 3 3 6 9
Sample Output
NoYes
#include <stdio.h> int main() { int n, num, s; while(~scanf("%d", &n)) { s = 0; while(n--) { scanf("%d", &num); s = s ^ num;//这个异或运算好像很神奇,感觉博弈就是找规律的题目 } if(s == 0) printf("No\n"); else printf("Yes\n"); } return 0; }
详解:
取石子游戏
两个人面队若干堆石子(或硬币,火柴,棋子)进行游戏。各堆含有
a1,a2,…,ak枚硬币。
游戏规则如下:
1. 两人轮流取子,当轮到你取子时,你不能不取
2. 取子者只能从某堆中取子,取走一堆中的任意个子
3. 最后取子者为游戏的得胜者,或当轮到你取子时,你没有子可取
你为败者。
:
结论1. 如果只有一堆,即k=1,则第一取子者胜;
结论2. 如果只有2堆,a1,a2, a1=a2则第2取子者胜;
第1取子者在某堆取走c个,则 第2取子者在另1堆也取走c个,
2堆仍然相等。
即 第1取子者取后2堆不相等, 第2取子者取后2堆相等,最后
取子者是 第2取子者.
结论3. 如果只有2堆,a1,a2, a1<>a2则第1取子者胜;
第1取子者在多的1堆取 abs(a1-a2)个,取后2堆相等。
定义: 如果有k堆,堆数用无序向量(a1,a2,...,ak)表示,如果第1
取子者不能获胜,则称 (a1,a2,...,ak)为必败点.
例 . k=2时,(a,a) 为必败点
结论4: 无序向量(a1,a2,...,ak),如果经过1次取子后变为必败点
则(a1,a2,...,ak)为必胜点, 无论如何取都不能变为必败点,则为
必败点 。
例 . k=2时,(20,25) 为必胜点 ,1次取子后变为必败点(20,20)
k=3 ,(20,20,25) 为必胜点 ,1次取子后变为必败点(20,20)
k=2,(20,20),无论如何取都变不了必败点,(20,20) 是必败点。
k=2时,相同(相等)必败,不等必胜。
看看C语言的异或运算^
性质1.若a=b,则a^b=0;
性质2.若a<>b,则a^b<>0;
性质3.若a^b=c,则a^c=b;
a^a^b=a^c ==> b=a^c;
性质4.令s=a1^a2^...^an,si是a1,a2,...,an中除 ai以外的其余n-1个
的异或值, 则
si=s^ai
性质5.令s=a1^a2^...^an.
若 s=0,则
si=ai ,(i=1,2,...,n )
当ai发生变化后,s<>0;
性质6.令A=(a1,a2,...,an),B=(b1,b2,...,bm,C=(a1,a2,...,an,b1,b2,...,bm).
记为C=A+B.
若A,B是必败点,则C是必败点
若A,B中有一个是必败点,另1个是必胜点,则C是必胜点.
两个必胜点之和不必是必胜点.
定义:若A+B是必败点,则称A与B等价若A==B, 则A与B等价
性质7. A+A 是必败点。
利用或运算^,结论2,结论3为
结论2‘k=2,如果a1^a2=0, 则第2人胜
结论3‘k=2,如果a1^a2<>0, 则第1人胜k>2 如何 ?
k=3. (a1,a2,a3) =(3,6,9)
3^6=5, 3^6^9=5^9<>0
对 (3,6,9)取子变为 (3,6,5) ,3^6^5=5^5=0
对 (3,6,5)无论如何取子都不能使其异或为0
一般地 有
定理 令s=a1^a2^...^ak,si=s^ai,
(1)若s<>0,则存在 i,将 ai缩小为si后 s=0;
(2)若s=0,则 将任何数ai做任何缩小后 s<>0;