P4980 【模板】Polya定理
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