题意
有一个
n
n
n个点的无向完全图,要对每条边染上
m
m
m种颜色的一种,问有多少种不不同的染色方案。两种染色方案同构当且仅当可以通过对其中一个图的点重标号后使其与另一个图完全相同。
n
≤
53
,
m
≤
1000
,
p
n\le53,m\le1000,p
n≤53,m≤1000,p为大于
n
n
n的素数。
分析
首先置换肯定有
n
!
n!
n!种,但我们无法枚举每种置换。注意到若两个置换中环的构成相同,则这两种置换的不动点的数目相同。要枚举不同环的构成只需要枚举
n
n
n的整数划分就好。
我们可以直接用Polya定理计算等价类数量,也就是
L
=
1
∣
G
∣
∑
g
∈
G
m
c
(
g
)
L=\frac{1}{|G|}\sum_{g\in G}m^{c(g)}
L=∣G∣1g∈G∑mc(g)其中
c
(
g
)
c(g)
c(g)表示置换
g
g
g下的不动点数量。
假设置换中有
s
k
s_k
sk个大小为
k
k
k的环,那么符合的置换数量为
n
!
∏
s
k
!
∗
k
s
k
\frac{n!}{\prod s_k!*k^{s_k}}
∏sk!∗kskn!
这是因为先要把
1
1
1到
n
n
n分配给每个环,然后一个大小为
k
k
k的环的方案为
(
k
−
1
)
!
(k-1)!
(k−1)!,且所有大小相同的环是无序的,所以还要除以一个
s
k
!
s_k!
sk!。
设第
i
i
i个环的大小为
c
i
c_i
ci,则该置换的不动点数量为
∏
i
m
⌊
c
i
2
⌋
∏
i
<
j
m
g
c
d
(
c
i
,
c
j
)
\prod_{i}m^{\lfloor\frac{c_i}{2}\rfloor}\prod_{i<j}m^{gcd(c_i,c_j)}
i∏m⌊2ci⌋i<j∏mgcd(ci,cj)
这是因为对于一个大小为
k
k
k的环,两点之间劣弧的不同长度有
⌊
k
2
⌋
\lfloor\frac{k}{2}\rfloor
⌊2k⌋种。而对于两个大小分别为
p
p
p和
q
q
q的环,在两个环上分别取一个点,两个点模
g
c
d
(
p
,
q
)
gcd(p,q)
gcd(p,q)意义下的差值共有
g
c
d
(
p
,
q
)
gcd(p,q)
gcd(p,q)种,且差值相等的两点之间的连边颜色必然相同。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
typedef long long LL;
const int N=60;
int n,m,MOD,s[N],c[N],tot,jc[N],ans;
int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y&1) ans=(LL)ans*x%MOD;
x=(LL)x*x%MOD;y>>=1;
}
return ans;
}
int gcd(int x,int y)
{
if (!y) return x;
else return gcd(y,x%y);
}
void calc(int mx)
{
int w=1;
for (int i=1;i<=tot;i++) s[c[i]]++,w=(LL)w*c[i]%MOD;
for (int i=1;i<=mx;i++) if (s[i]) w=(LL)w*jc[s[i]]%MOD,s[i]=0;
int t=0;
for (int i=1;i<=tot;i++)
{
t+=c[i]/2;
for (int j=i+1;j<=tot;j++) t+=gcd(c[i],c[j]);
}
w=(LL)ksm(w,MOD-2)*ksm(m,t)%MOD;
(ans+=w)%=MOD;
}
void dfs(int x,int ret)
{
if (!ret) {calc(x-1);return;}
if (ret<x) return;
if (x==ret) c[++tot]=x,dfs(x+1,0),tot--;
else
{
dfs(x+1,ret);
int tmp=tot;
for (int i=x;i<=ret;i+=x) c[++tot]=x,dfs(x+1,ret-i);
tot=tmp;
}
}
int main()
{
scanf("%d%d%d",&n,&m,&MOD);
jc[0]=1;
for (int i=1;i<=n;i++) jc[i]=(LL)jc[i-1]*i%MOD;
dfs(1,n);
printf("%d\n",ans);
return 0;
}