Polya定理
置换群中的概念(数学表达):
(M=frac{1}{G}sumlimits_{i=1}^g m^c)
G:表示置换的个数,m表示颜色种类(方案中不一定使用全部颜色),c表示每种置换的循环节个数
注释:循环节个数解释:
[left[
egin{array}{cc}
1&2&3&4\
1&4&3&2
end{array}
ight]
]
这为三个循环节,分别是[1],[3],[2,4];
[left[
egin{array}{cc}
1&2&3&4\
4&1&2&3
end{array}
ight]
]
这是一个循环[1,2],[2,3],[3,4],[4,1],可以合并成[1];
目前认识到:置换分为两大类(egin{cases} ext{旋转:旋转i步的循环为gcd(i,n)}\ ext{翻转:}egin{cases} ext{n为奇数,c=n+1/2}\ ext{n为偶数}frac{1}{2}c=n/2,frac{1}{2}c=n/2+1end{cases} end{cases})
证明待补充
例题:
1.poj2409
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
inline int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
inline int poww(int a,int b){
int ans=1;
while(b){
if(b&1)ans*=a;
b>>=1;
a*=a;
}
return ans;
}
int main(){
while(1){
scanf("%d%d",&m,&n);
if(m==0&&n==0)break;
int c=0;
for(int i=0;i<n;++i)c+=poww(m,gcd(i,n));
if(n&1)c+=n*poww(m,(n+1)/2);
else c+=n/2*poww(m,n/2)+n/2*poww(m,n/2+1);
cout<<c/(2*n)<<endl;
}
return 0;
}
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int t,n,p,tot,cnt;
int prime[1000000],v[1000000];
inline void pre(){
for(int i=2;i<=100000;++i){
if(!v[i]){
prime[++tot]=i;
v[i]=i;
}
for(int j=1;j<=tot;++j){
if(prime[j]*i>100000||prime[j]>v[i])break;
v[i*prime[j]]=prime[j];
}
}
}
inline int poww(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans%p;
}
inline int euler(int x){
int ans=x;
for(int i=1;i<=tot&&prime[i]*prime[i]<=x;++i){
if(x%prime[i]==0){
ans=ans/prime[i]*(prime[i]-1);
while(x%prime[i]==0)x/=prime[i];
}
}
if(x>1)ans=ans/x*(x-1);
return ans;
}
int main(){
pre();
cin>>t;
for(int i=1;i<=t;++i){
cin>>n>>p;
int c=0;
for(int j=1;j<=sqrt(n);++j){
if(n%j==0){
c=(c+euler(n/j)%p*poww(n%p,j-1)%p)%p;
if(j*j!=n)c=(c+euler(j)%p*poww(n%p,n/j-1)%p)%p;
}
}
cout<<c%p<<endl;
}
return 0;
}