Pólya 计数
参考资料
简介
Pólya 计数定理(Pólya Enumeration Theorem)用于求解涉及对称性的「本质不同」计数,是 Burnside 引理(Burnside's Lemma)在染色问题上的应用。
设群 作用在集合 上,本质相同即同一轨道。Burnside 引理给出轨道数:
其中 是 的不动点集合。
对染色问题,用 种颜色染 中各点。若置换 的轮换分解含 个轮换,则同一轮换内必须同色,故 。代入得 Pólya 计数定理:
以 个珠子的项链为例,仅计旋转时空间对称群是循环群 。旋转 次的置换有 个轮换,按因子合并同类项,得本质不同的 色染色方案数:
枚举 的因子,单点欧拉函数用 求出,快速幂计算 ,再乘 的逆元。时间复杂度为 。
实现
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int mod=1000000007;
ll Pow(ll x,ll y)
{
x%=mod;
ll res=1;
while(y)
{
if(y&1)res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
int phi(int n)
{
int res=n;
for(int i=2;i*i<=n;i++)
{
if(n%i)continue;
res=res/i*(i-1);
while(n%i==0)n/=i;
}
if(n>1)res=res/n*(n-1);
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
ll ans=0;
for(int i=1;i*i<=n;i++)
{
if(n%i)continue;
ans=(ans+(ll)phi(i)*Pow(n,n/i))%mod;
if(i!=n/i)ans=(ans+(ll)phi(n/i)*Pow(n,i))%mod;
}
ans=ans*Pow(n,mod-2)%mod;
cout<<ans<<'\n';
}
return 0;
}