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 }

 

posted @ 2020-07-28 22:23  programmer_w  阅读(0)  评论(0)    收藏  举报