Lunch HDU - 6892 SG函数

题目链接

题意
题目大意
给出n 个数,对于每个数 x 可以将每个数分成k个大小相等的数\(\frac{x}{k}\)(k>2且k时x的因子),1 不可再分,问什么时候先手会胜。

思路

对于每个数,显然是1 必败,而 质数 必胜。

否则对于一个数n ,从2 到n,将n 按题意分解,
根据SG函数的性质,设\(n = p ∗ q\)

  • 若p 为偶数,那么可以得出其能到达的子局面的SG值为0(偶数个相同的数异或起来为0);

  • 若p 为奇数,那么最终的SG值取决于SG(q)

但是 n 很大,无法暴力解决。我们对前一百个数打表求SG值。

通过打表,观察找规律可知:

  • 若一个数的质因数分解式含有2 ,无论有多少2 ,对SG值的贡献只能是1 ,
  • 奇质数对SG值的贡献是该质数的个数。

因此对于长度为l的巧克力,sg(l)等于l的非2质因数的指数和+l是否为偶数
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int p[maxn], cnt;
int flag[maxn];

void prime()
{
    for(int i = 2; i < maxn; i++)
    {
        if(!flag[i]) p[cnt++] = i;
        for(int j = 0; p[j] < maxn / i; j++)
        {
            flag[p[j] * i] = 1;
            if(i % p[j] == 0) break;
        }
    }
}

int sg(int x)
{
    int res = 0;
    for(int i = 0; i < cnt && p[i] <= x / p[i]; i++)
    {
        if(x % p[i] == 0)
        {
            if(p[i] == 2)
            {
                res++;
                while(x % p[i] == 0)
                    x /= p[i];
            }
            else
            {
                while(x % p[i] == 0)
                    x /= p[i], res++;
            }
        }
    }
    if(x > 1) res++;
    return res;

}

int main()
{
    prime();
    int t; scanf("%d", &t);
    while(t--)
    {
        int n; scanf("%d", &n);
        int res = 0;
        for(int i = 1; i <= n; i++)
        {
            int x; scanf("%d", &x);
            res ^= sg(x);
        }
        printf("%s\n", res ? "W" : "L");
    }
}

————————————————
版权声明:本文为CSDN博主「Happig丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44691917/article/details/113384223

posted @ 2022-09-15 14:35  kingwzun  阅读(24)  评论(0编辑  收藏  举报