1. 程式人生 > >P4980 【模板】Polya定理

P4980 【模板】Polya定理

fine isp 染色 結果 pla 直接 只需要 for arp

P4980 【模板】Polya定理

題目描述

給定一個\(n\)個點,\(n\)條邊的環,有\(n\)種顏色,給每個頂點染色,問有多少種本質不同的染色方案,答案對\(10^9+7\)取模

註意本題的本質不同,定義為:只需要不能通過旋轉與別的染色方案相同

輸入輸出格式

輸入格式:

第一行輸入一個\(t\),表示有\(t\)組數據

第二行開始,一共\(t\)行,每行一個整數\(n\),意思如題所示。

輸出格式:

\(t\)行,每行一個數字,表示染色方案數對\(10^9+7\)取模後的結果

說明

\(n \leq 10^9,t \leq 10^3\)


註意置換只有\(n\)個,表示旋轉的度數,沒有翻轉。

那麽一個旋轉\(i\)個點的置換的循環個數應該為\(\gcd(i,m)\)

帶到\(Polya\)定理裏面去,方案數為

\[\frac{1}{n}\sum_{i=1}^n n^{\gcd(i,n)}\]

\[=\frac{1}{n}\sum_{i=1}^n n^k\sum_{k=1}^n[\gcd(i,n)=k]\]

\[=\frac{1}{n}\sum_{k\mid n} n^k\sum_{k=1}^n[\gcd(i,n)=k]\]

\[=\sum_{k\mid n} n^{k-1}\sum_{k=1}^{\frac{n}{k}}[\gcd(i,n)=1]\]

\[=\sum_{k|n}n^{k-1}\varphi(\frac{n}{k})\]

然後直接暴力搞,復雜度是常數很小的\(O(Tn^{\frac{3}{4}})\)


Code:

#include <cstdio>
const int mod=1e9+7;
int Euler(int n)
{
    int phi=n;
    for(int i=2;i*i<=n;i++)
        if(n%i==0)
        {
            phi=phi-phi/i;
            while(n%i==0) n/=i;
        }
    if(n!=1) phi=phi-phi/n;
    return phi;
}
#define mul(a,b) (1ll*(a)*(b)%mod)
#define add(a,b) ((a+b)%mod)
int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
int Polya(int n)
{
    int ans=0;
    for(int i=1;i*i<=n;i++)
    {
        if(n%i) continue;
        ans=add(ans,mul(qp(n,i-1),Euler(n/i)));
        if(i*i!=n)
            ans=add(ans,mul(qp(n,n/i-1),Euler(i)));
    }
    return ans;
}
int main()
{
    int n,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        printf("%d\n",Polya(n));
    }
    return 0;
}

2018.12.21

P4980 【模板】Polya定理