题目:https://acm.hdu.edu.cn/showproblem.php?pid=6892
根据sg定理,只需要求出每个数的sg[x];
对于一个数x,如果是1是必败,sg[1]=0;
如果是质数,那么必胜,sg[质数]=1;
其他的则将x分解成若干对非1因数(p1,q1,p2,q2,p3,q3......)
如果某对因数里有一个为偶数,则异或起来是为0的;
如果某对因数里有一个p1为奇数,则异或起来是sg[q1]的;
#include<stdio.h> #include<bits/stdc++.h> using namespace std; int sg[10010]; int vis[1005]; int dfs(int u) { if (sg[u]!=-1) return sg[u]; memset(vis,0,sizeof(vis)); for (int i = 2, k; i <= u; i++) { if (u % i == 0) { k = u / i; if (i & 1) vis[dfs(k)] = 1; else vis[0] = 1; } } for (int i = 0;; i++) if (!vis[i]) return sg[u] = i; } void init() { memset(sg, -1, sizeof sg); sg[1] = 0; for (int i = 1; i <= 400; i++) { dfs(i); cout << "(" << i << "," << sg[i] << ") "; } } int main() { init(); }
得出规律是sg[x]是奇质因数的次数;
如果因数有2就加1;//因为2是质数,所以sg[2]是必胜态=1,但只用算一次
因数没有2就不加;
再根据Nim博弈把sg值异或起来