Burnside定理及polya定理小记
例题
Burnside定理:
定义:
设
举例:
不妨拿例题来举例,当
显然
对于
对于
对于
显然等式左边等于等式右边
证明:
考虑引入轨道稳定子定理:
考虑证明该定理:
首先可以证明
封闭性:
结合律:显然置换的乘法满足结合律
单位元:因为
逆元:若
而
而根据群论中拉格朗日定理,可得:
其中
若
反过来可证,若
以上两点说明对于一个
又显然
然后就可以开始证明了:
证毕。
Polya定理
在于 Burnside 引理相同的前置条件下,内容修改为:
其中
证明:
显然就是要证明
最后再用一条连等式来总结:
而对于
例题解析:
显然可以根据
剩下显然就是欧拉函数和快速幂,这里不多赘述,上代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int T,n,ans;
int ksm(int ds,int zs)
{
int re=1;
while(zs)
{
if(zs&1) re=re*ds%mod;
ds=ds*ds%mod;
zs=zs/2;
}
return re;
}
int get_phi(int x)
{
int re=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
re=re-re/i;
while(x%i==0) x=x/i;
}
}
if(x!=1) re=re-re/x;
return re;
}
signed main()
{
scanf("%lld",&T);
while(T--)
{
ans=0;
scanf("%lld",&n);
for(int i=1;i*i<=n;i++)
{
if(n%i==0)
{
ans=(ans+get_phi(i)*ksm(n,n/i)%mod)%mod;
if(i*i!=n) ans=(ans+get_phi(n/i)*ksm(n,i)%mod)%mod;
}
}
ans=ans*ksm(n,mod-2)%mod;
printf("%lld\n",ans);
}
return 0;
}
例题1.2
因为每种颜色使用有限制,所以显然不能直接使用
考虑对于一个置换操作
而将每个
上代码:
#include<bits/stdc++.h>
using namespace std;
int sr,sb,sg,n,m,p,ans,inv;
int f[22][22][22];
int a[100],c[100],idx;
bool vis[100];
int ksm(int ds,int zs)
{
int re=1;
while(zs)
{
if(zs&1) re=re*ds%p;
ds=ds*ds%p;
zs=zs/2;
}
return re;
}
void dfs(int wz)
{
vis[wz]=true;
c[idx]++;
if(!vis[a[wz]]) dfs(a[wz]);
}
void calc()
{
memset(f,0,sizeof f);
f[0][0][0]=1;
for(int i=1;i<=idx;i++)
{
for(int re=sr;re>=0;re--)
for(int bl=sb;bl>=0;bl--)
for(int gr=sg;gr>=0;gr--)
{
f[re][bl][gr]=0;
if(re>=c[i]) (f[re][bl][gr]+=f[re-c[i]][bl][gr])%=p;
if(bl>=c[i]) (f[re][bl][gr]+=f[re][bl-c[i]][gr])%=p;
if(gr>=c[i]) (f[re][bl][gr]+=f[re][bl][gr-c[i]])%=p;
}
}
(ans+=f[sr][sb][sg])%=p;
}
int main()
{
scanf("%d %d %d %d %d",&sr,&sb,&sg,&m,&p);
n=sr+sb+sg,inv=ksm(m+1,p-2);
idx=0;
for(int i=1;i<=n;i++)
a[i]=i,vis[i]=false;
for(int i=1;i<=n;i++) if(!vis[i]) idx++,dfs(i);
calc();
while(m--)
{
idx=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),vis[i]=false;
for(int i=1;i<=n;i++) if(!vis[i]) idx++,c[idx]=0,dfs(i);
calc();
}
printf("%d\n",ans*inv%p);
return 0;
}