思路
polya模版题。
what is polya?
我们可以发现,一个循环节之间的“不变元素”可以互相交换从而不影响整体,所以我们可以设Ci为置换群i的循环节个数。
例如(1 2 3 4 5
3 5 1 4 2)
的循环节就为:1和3循环1->3->1……
2和5循环2->5->2……
4和它自身循环4->4->4……
那么循环节数就为3
再回来看现在这个题目,我们可以抽象地把Ci替换掉Di
那么Di=p^C(i) (p为总共的字母数)
相同循环节中的元素可以互相置换,所以Di=p^C(i)
polya公式为1/|G|(p^C(1)+p^C(2)+……+p^C(s))
以4为例,则1/|G|=1/4
C(1):循环节为(1)(2)(3)(4),所以C(1)=4
C(2):循环节为(4 3 2 1),所以C(2)=1
C(3):循环节为(1 3)(2 4),所以C(3)=2
C(4):循环节为(1 2 3 4),所以C(4)=1
那么答案就为1/4(2^4+2^1+2^2+2^1)=6
这里的C相对于上面的D来说要简单,记得XJR学长给我讲过环的判定,直接任选一个没有选过的点,从这个点开始映射,走过的点标上1,等到再走到标上1时,结束,统计数加1
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=1e9+7,maxn=2e5+77;
int b[maxn],n,s=0,ass=0;
bool f[maxn];
void fin(int t)
{
int i=t;
f[i]=1;
while(!f[b[i]])
{
i=b[i]; f[i]=1;
}
return;
}
int polya()
{
int t=0;
memset(f,0,sizeof(f));
for(int i=1; i<=n; i++) if(!f[b[i]]) fin(i),t++;
return t;
}
void P(int x,int t)
{
if(!x) return;
if(x%2==0)
{
P(x/2,t);
s=(s*s)%mod;
}else
{
P(x/2,t);
s=(s*s)%mod; s=s*t%mod;
}
return;
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
for(int j=1; j<=n; j++) b[j]=(j+i)%n+1;
s=1;
P(polya(),2);
ass+=s;
}
printf("%d",ass/n);
}