SG函数
基础SG
1 #include <cstdio> 2 #include <algorithm> 3 #define rep(i,a,b) for(int i = a; i <= b; i++) 4 const int N = 1000+10; 5 using namespace std; 6 int f[20],sg[N],n,m,p; 7 8 int solve(int x) 9 { 10 if(sg[x] != -1) return sg[x]; 11 int vis[2005]; memset(vis,0,sizeof vis); 12 rep(i,1,15){ 13 if(x < f[i]) break; 14 vis[solve(x-f[i])] = 1; //多种后继状态取mex 15 } 16 rep(i,0,2000) 17 if(!vis[i]) return sg[x] = i; //取mex的过程 18 } 19 20 int main() 21 { 22 f[1] = 1, f[2] = 2; 23 rep(i,3,15) f[i] = f[i-1]+f[i-2]; //求出斐波那契数 24 memset(sg,-1,sizeof sg); sg[0] = 0; //若数据唯一可以将mem放在一次即可,不然得放在里面 25 while(~scanf("%d%d%d",&n,&m,&p)){ 26 if(n == 0 && m == 0 && p == 0) break; 27 if((solve(n)^solve(m)^solve(p)) == 0) printf("Nacci\n"); 28 else printf("Fibo\n"); 29 } 30 return 0; 31 }
多种情况SG
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) 6 #define rep(i,a,b) for(int i = a; i <= b; i++) 7 #define LOG1(x1,x2) cout << x1 << ": " << x2 << endl; 8 #define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl; 9 #define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl; 10 typedef long long ll; 11 typedef double db; 12 const int N = 1000+10; 13 const int M = 1e5+100; 14 const db EPS = 1e-9; 15 using namespace std; 16 17 int sg[N],n; 18 19 int solve(int x) 20 { 21 if(sg[x] != -1) return sg[x]; 22 int vis[2010]; memset(vis,0,sizeof vis); 23 int ans[2010]; //记录每一个约数 24 int tp = 0, ct = 0; 25 rep(i,1,x-1){ 26 if(x%i == 0){ 27 ans[++ct] = solve(i); 28 tp ^= ans[ct]; 29 } 30 } 31 rep(i,1,ct) vis[tp^ans[i]] = 1; //枚举每一个子状态 32 rep(i,0,2000) 33 if(vis[i] == 0) return sg[x] = i; 34 } 35 36 int main() 37 { 38 memset(sg,-1,sizeof sg); 39 sg[1] = 0; 40 while(~scanf("%d",&n)){ 41 int ans = 0; 42 rep(i,1,n){ 43 int xx; scanf("%d",&xx); 44 ans ^= solve(xx); 45 } 46 if(ans == 0) printf("rainbow\n"); 47 else printf("freda\n"); 48 } 49 return 0; 50 }
二维SG
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) 6 #define rep(i,a,b) for(int i = a; i <= b; i++) 7 #define LOG1(x1,x2) cout << x1 << ": " << x2 << endl; 8 #define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl; 9 #define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl; 10 typedef long long ll; 11 typedef double db; 12 const int N = 1000+10; 13 const int M = 1e5+100; 14 const db EPS = 1e-9; 15 using namespace std; 16 17 int sg[N][N]; 18 19 int solve(int n,int m) 20 { 21 if(sg[n][m] != -1) return sg[n][m]; 22 int vis[1005]; memset(vis,0,sizeof vis); 23 rep(i,2,n/2){ //双方采取最优策略进行行动,一定不会剪出1*x或x*1的情况 24 int x = solve(i,m); 25 int y = solve(n-i,m); 26 vis[x^y] = 1; 27 } 28 rep(i,2,m/2){ 29 int x = solve(n,i); 30 int y = solve(n,m-i); 31 vis[x^y] = 1; 32 } 33 rep(i,0,1005) 34 if(vis[i] == 0) return sg[n][m] = i; 35 } 36 37 int main() 38 { 39 int n,m; 40 memset(sg,-1,sizeof sg); 41 sg[2][2] = 0, sg[2][3] = 0, sg[3][2] = 0; //双方都按最优策略进行,不会出现 n=1,m>=3 或者 n>=3,m=1 的情况。 42 //因此最后的状态是(2,2)、(2,3)、(3,2) 43 while(~scanf("%d%d",&n,&m)) 44 { 45 if(solve(n,m) == 0) printf("LOSE\n"); 46 else printf("WIN\n"); 47 } 48 return 0; 49 }
SG打表
1 int sg[maxn]; 2 int main() 3 { 4 sg[0] = 0; 5 int st = 1; 6 int end = maxn; 7 for (int i = st;i <= end;i++) { 8 set<int>s; 9 /* for (int j = 2;j <= 9; j++) { 10 int temp = i / j; 11 if (i % j) temp++; 12 s.insert(sg[temp]); 13 }*/ 14 /* for (int j = st; j <= i - 1;j++) { 15 if((i^j)<i) 16 s.insert(sg[i ^ j] ^ sg[j]); 17 }*/ 18 //满足条件的直接外面包装一个sg[]塞入set. 19 int now = 0; 20 while (s.count(now)) now++; 21 sg[i] = now; 22 } 23 rep(i, st, end) { 24 if (sg[i])printf("Stan wins.\n");//根据题目改变 25 else printf("Ollie wins.\n"); 26 } 27 }