Fibonacci again and again
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11221 Accepted Submission(s): 4838
遇到的第一道需要使用sg函数的题目。
这里转一个推导。反正自己一下子想不明白。
首先确定这样的博弈游戏属不属于组合游戏的范畴:
1、有且仅有两个玩家 2、游戏双方轮流操作 3、游戏操作状态是个有限的集合(比如:取石子游戏,石子是有限的,棋盘中的棋盘大小的有限的) 4、游戏必须在有限次内结束 5、当一方无法操作时,游戏结束。
例子推导
例如:取石子问题,有1堆n个的石子,每次只能取{1,3,4}个石子,先取完石子者胜利,那么各个数的SG值为多少?
sg[0]=0,f[]={1,3,4},
x=1时,可以取走1-f{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1;
x=2时,可以取走2-f{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0;
x=3时,可以取走3-f{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1;
x=4时,可以取走4-f{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;
x=5时,可以取走5-f{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;
以此类推.....
x 0 1 2 3 4 5 6 7 8....
sg[x] 0 1 0 1 2 3 2 0 1....
计算从1-n范围内的SG值。
f(存储可以走的步数,f[0]表示可以有多少种走法)
f[]需要从小到大排序
1.可选步数为1~m的连续整数,直接取模即可,SG(x) = x % (m+1);
2.可选步数为任意步,SG(x) = x;
3.可选步数为一系列不连续的数,用getSG()计算
那么这个题的标程
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<vector> 8 #define mem(a,b) memset(a,b,sizeof(a)) 9 #define ll long long 10 #define inf 1000000000 11 #define maxn 1005 12 #define maxm 100005 13 #define eps 1e-10 14 #define for0(i,maxn) for(int i=1;i<=(maxn);++i) 15 #define for1(i,maxn) for(int i=1;i<=(maxn);++i) 16 #define for2(i,x,y) for(int i=(x);i<=(y);++i) 17 #define for3(i,x,y) for(int i=(x);i>=(y);--i) 18 #define mod 1000000007 19 using namespace std; 20 inline int read() 21 { 22 int x=0,f=1;char ch=getchar(); 23 while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} 24 while(ch>='0'&&ch<='9') {x=10*x+ch-'0';ch=getchar();} 25 return x*f; 26 } 27 int f[maxn],sg[maxn],hash1[maxn]; 28 void getSG(int n) 29 { 30 mem(sg,0); 31 for(int i=1;i<=n;++i) 32 { 33 mem(hash1,0); 34 for(int j=1;f[j]<=i;j++) 35 hash1[sg[i-f[j]]]=1; 36 for(int j=0;j<=n;++j) 37 { 38 if(hash1[j]==0) { 39 sg[i]=j;break; 40 } 41 } 42 } 43 } 44 int main() 45 { 46 int m,n,t; 47 f[0]=f[1]=1; 48 for(int i=2;i<=16;++i) 49 f[i]=f[i-1]+f[i-2]; 50 getSG(1000); 51 while(~scanf("%d%d%d",&n,&m,&t)) 52 { 53 if(m==0&&n==0&&t==0) break; 54 if((sg[n]^sg[m]^sg[t])==0) 55 puts("Nacci"); 56 else puts("Fibo"); 57 } 58 return 0; 59 }