取石子游戲(找規(guī)律+sg函數(shù)+博弈)HDU 5795 A Simple Nim
題面:
A Simple Nim
Time Limit: 2000/1000 MS (Java/Others)????Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 300????Accepted Submission(s): 211
Problem Description
Two players take turns picking candies from n heaps,the player who picks the last one will win the game.On each turn they can pick any number of candies which come from the same heap(picking no candy is not allowed).To make the game
more interesting,players can separate one heap into three smaller heaps(no empty heaps)instead of the picking operation.Please find out which player will win the game if each of them never make mistakes.
?
Input
Intput contains multiple test cases. The first line is an integer
1≤T≤100,
the number of test cases. Each case begins with an integer n, indicating the number of the heaps, the next line contains N integers
s[0],s[1],....,s[n?1],
representing heaps with s[0],s[1],...,s[n?1]
objects respectively.(1≤n≤106,1≤s[i]≤109)
?
Output
For each test case,output a line whick contains either"First player wins."or"Second player wins".
?
Sample Input
2
2
4 4
3
1 2 4
?
Sample Output
Second player wins.
First player wins.
?
Author
UESTC
?
Source
2016 Multi-University Training Contest 6
?
題意:
??? 取石子游戲,有兩種操作方式,一、在一堆中取任意顆石子,(大于0)。二、將一堆分成三堆,每堆數(shù)量大于0。取到最后一塊石子的人獲得勝利。
解題:
??? 先小數(shù)據(jù)打表求sg值,可以發(fā)現(xiàn)sg值的規(guī)律。當(dāng)i%8==7時(shí),其sg值為i+1,當(dāng)i%8==0時(shí),其sg值為i-1(sg[0]=0)。一個(gè)狀態(tài)的sg值,是其后繼狀態(tài)sg值中未出現(xiàn)過(guò)最小整數(shù),三堆的sg值是三堆石子數(shù)量sg值的異或。根據(jù)sg值的規(guī)律,可以求解問(wèn)題,官方題解說(shuō)是用數(shù)學(xué)歸納法證明。
代碼:
#include#include#include#define?LL?long?long #define?mod?1000000007 #define?sz?100005 using?namespace?std; int?sg[sz]; bool?vis[sz]; int?main() { //打表程序 /*int?tmp; ????sg[0]=0; for(int?i=1;i<=50;i++) { memset(vis,0,sizeof(vis)); for(int?j=0;j<i;j++) vis[sg[j]]=1; for(int?k=1;k<i;k++) { for(int?m=1;m0) ????????????????{ tmp=sg[k]^sg[m]^sg[u]; vis[tmp]=1; } else break; } } for(int?x=0;;x++) if(!vis[x]) { sg[i]=x; printf("sg[%d]:?%dn",i,x); break; } }*/ int?t,n,tmp,s; scanf("%d",&t); ????while(t--) { s=0; scanf("%d",&n); ????????while(n--) { scanf("%d",&tmp); if(tmp%8==7) s^=(tmp+1); else?if(tmp%8==0) s^=(tmp-1); else s^=tmp; } if(s) printf("First?player?wins.n"); else printf("Second?player?wins.n"); } return?0; }