其他分享
首页 > 其他分享> > P4980 Pólya 定理 + DFS

P4980 Pólya 定理 + DFS

作者:互联网

题意

传送门 P4980 【模板】Pólya 定理

题解

根据 Pólya 定理,本质不同的染色方案数为
1 n ∑ k = 0 n − 1 n g c d ( n , k ) \frac{1}{n}\sum\limits_{k=0}^{n-1}n^{gcd(n,k)} n1​k=0∑n−1​ngcd(n,k) 式中满足 g c d ( n , k ) = d gcd(n,k)=d gcd(n,k)=d 的 k k k 的数量为 ϕ ( n / d ) \phi(n/d) ϕ(n/d),合并这样的项得到
1 n ∑ d ∣ n ϕ ( d ) n n / d \frac{1}{n}\sum\limits_{d\vert n}\phi(d)n^{n/d} n1​d∣n∑​ϕ(d)nn/d 预处理出 n n n 的素因子, D F S DFS DFS 计算所有的约数并统计答案即可。总时间复杂度 O ( t ( n + ∑ d ∣ n log ⁡ n ) ) O\Big(t(\sqrt{n}+\sum\limits_{d\vert n}\log{n})\Big) O(t(n ​+d∣n∑​logn))。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7, MAXLG = 35;
int pn, prime[MAXLG], num[MAXLG];
int T, N;
ll Res;

ll pow_mod(ll x, int n, int mod)
{
    ll res = 1;
    while (n)
    {
        if (n & 1)
            res = res * x % mod;
        x = x * x % mod, n >>= 1;
    }
    return res;
}

void dfs(int k, int n, int ph, int d)
{
    if (k == pn)
    {
        Res = (Res + pow_mod(N, N / d, MOD) * ph % MOD) % MOD;
        return;
    }
    int p = prime[k];
    if (n < num[k])
        dfs(k, n + 1, ph * (n == 0 ? p - 1 : p), d * p);
    dfs(k + 1, 0, ph, d);
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> T;
    while (T--)
    {
        cin >> N;
        pn = Res = 0;
        int t = N;
        for (int i = 2; i * i <= t; ++i)
            if (t % i == 0)
            {
                prime[pn] = i, num[pn] = 0;
                while (t % i == 0)
                    t /= i, ++num[pn];
                ++pn;
            }
        if (t != 1)
            prime[pn] = t, num[pn++] = 1;
        dfs(0, 0, 1, 1);
        cout << Res * pow_mod(N, MOD - 2, MOD) % MOD << '\n';
    }
    return 0;
}

标签:P4980,dfs,int,ll,DFS,num,lya,pn,mod
来源: https://blog.csdn.net/neweryyy/article/details/122396087