首页 > 其他 > 详细

2020CCPC网络选拔赛 1005 Lunch 博弈论 打表 SG函数 找规律

时间:2020-09-25 20:53:18      阅读:63      评论:0      收藏:0      [点我收藏+]

2020CCPC网络选拔赛 1005 Lunch 博弈论 打表 SG函数 找规律

题意

\(n\)堆石子,现可以对一堆石子选择一个整数\(L,(L > 1)\),将这堆石子再分成\(L\)\(\frac{a_i}{L}\)的石子。

最后无法进行操作的人输掉。

问先手获胜还是后手获胜。

\[1\leq t \leq 2 \times 10^4,1\leq n \leq 10,1\leq l_i \leq 10^9 \]

分析

\(n\)这么小,一看就很难直接看出性质做题。

考虑用\(SG\)函数打表看看。

显然我们要对每个长度求\(SG\)函数。

\[sg[k] = mex_{d|k ,d > 1}(d 个 SG(k/d)异或和) \]

\(SG[1] = 0\)

打表程序

int SG[35];

int sg(int x) {
    if(SG[x] != -1) return SG[x];
    unordered_map<int, int> mp;
    vector<int> v;
    for (ll i = 2; i * i <= x; i++) {
        if (x % i) continue;
        v.push_back(i);
        if (i * i != x) v.push_back(x / i);
    }
    v.push_back(x);
    for (int i = 0; i < v.size(); i++) {
        if (v[i] % 2 == 0) mp[0]++;
        else mp[sg(x / v[i])]++;
    }
    for (int i = 0;; i++) {
        if (!mp[i]) return SG[x] = i;
    }
}

int main() {
    memset(SG, -1, sizeof SG);
    SG[1] = 0;
    for (int i = 1; i <= 30; i++)
        cout << i << ‘ ‘ << sg(i) << ‘\n‘;
}

得出结论

\[SG[k] = k的奇数质因子个数 + [k为偶数] \]

所以只要能得出\([1,10^9]\)的质因数分解即可。

考虑经典的试除法即可。

代码

艰难卡常

2043ms

const int M = 4e4 + 5;

int prime[M];
int vis[M];
int cnt;

int euler_sieve(int n) {
    int cnt = 0;
    for (re int i = 2; i <= n; i++) {
        if (!vis[i]) prime[cnt++] = i;
        for (re int j = 0; j < cnt; j++) {
            if (i * prime[j] > n) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    return cnt;
}


int main() {
    cnt = euler_sieve(M - 3);
    int T = readint();
    int n;
    int res;
    int tmp, x,tot;
    while (T--) {
        n = readint();
        res = 0;
        for (re int i = 0; i < n; i++) {
            tmp = readint();
            x = tmp;
            tot = (x % 2 == 0);
            while (x % 2 == 0) x /= 2;
            for (re int i = 1; i < cnt; i++) {
                if (x % prime[i]) continue;
                while (x % prime[i] == 0) {
                    x /= prime[i];
                    tot++;
                }
                if ((ll)prime[i] * prime[i] > x) break;
            }
            if (x != 1 && x != 2) tot++;
            res ^= tot;
        }
        if (res) puts("W");
        else puts("L");
    }
}

2020CCPC网络选拔赛 1005 Lunch 博弈论 打表 SG函数 找规律

原文:https://www.cnblogs.com/hznumqf/p/13732351.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!