一、题目
题目描述
有长度为 n n n的环 m m m染色,问翻转和旋转之后本质不同的方案数。
数据范围
n m ≤ 32 nm\leq32 nm≤32
二、解法
polya \text{polya} polya版题,一共 2 n 2n 2n个置换。
首先考虑旋转,旋转 i i i次后的分解个数为 gcd ( i , n ) \gcd(i,n) gcd(i,n),贡献为 ∑ i = 1 n m gcd ( i , n ) \sum_{i=1}^nm^{\gcd(i,n)} ∑i=1nmgcd(i,n)
然后考虑翻转,分奇偶性讨论,如果为偶数,那么过两点有 n 2 \frac{n}{2} 2n的贡献是 m n / 2 + 1 m^{n/2+1} mn/2+1,那么过空隙有 n 2 \frac{n}{2} 2n的贡献是 m n / 2 m^{n/2} mn/2;如果为奇数,那么只能过一点和一个空隙,一共有 n n n个,贡献为 m n / 2 + 1 m^{n/2+1} mn/2+1
#include <cstdio>
#define int long long
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,ans;
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
int qkpow(int a,int b)
{
int r=1;
while(b>0)
{
if(b&1) r=r*a;
a=a*a;
b>>=1;
}
return r;
}
signed main()
{
while(~scanf("%lld %lld",&m,&n) && n+m)
{
ans=0;
if(!n)
{
puts("0");
continue ;
}
for(int i=1;i<=n;i++)
ans+=qkpow(m,gcd(i,n));
if(n&1) ans+=n*qkpow(m,n/2+1);
else ans+=(n/2)*qkpow(m,n/2)+(n/2)*qkpow(m,n/2+1);
ans/=2*n;
printf("%lld\n",ans);
}
}