题目: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值异或起来