这两道题一样啊,只是一个规定颜色个数,一个不规定罢了。
题解的话就讲2409这道题吧
题意:用m种颜色染长度为n的环,旋转和对称认为是同一种方案,求本质不同的方案数。
我们只要考虑出置换群G,直接套polya公式即可。
(polya定理公式及证明在我的另一篇博客里有详细说明)
首先,考虑一下旋转。
对于旋转,所有的节点都会旋转,所以循环节长度应该是一样的,这个长度是多长呢?
设每次转x格,现在在p号点,走k次后回到p点,即
所以kx模n等于0,即kx是n的倍数。
当然kx还是x的倍数,而k是循环节长度,要取最小,则满足以上两个条件的最小的kx是lcm(x,n)。
把lcm换成gcd
也就是说,循环节长度是n/gcd(x,n),意义是在每次转x格的前提下,n/gcd(x,n)个数分别在来回交换。
也就是每n/gcd(x,n)个为一组,把n分成好几组,显然分成了gcd(x,n)组,所以
对于旋转,循环节长度n/gcd(x,n),循环节个数gcd(x,n),而每次可以条0步,1步…n-1步,所以共有n种置换。
(以上证明部分转自http://blog.csdn.net/braketbn/article/details/50669362)
然后考虑对称。
分奇偶讨论
奇数:对称轴一定是经过一个点和它的对边,共有n个对称轴,假设对称轴是穿过n节点,那么在对称中n+1和n-1互换,n+2和n-2互换,这样共有(n-1)/2+1(对称轴穿过的点本身是一个循环节)个循环节。
偶数:
分情况讨论对称轴穿过两个点还是两条边。
两条边:n/2个置换,每个置换的循环节个数都是n/2
两个点:n/2个置换,每个置换循环节个数是(n-2)/2+2=n/2+1
最后别忘了除以|G|=n+n/2+n/2=2*n
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int c,n,i,ans;
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
int qpow(int x,int y)
{
int ret=1;
for (;y;y>>=1,x=x*x)
{
if (y&1)ret*=x;
}
return ret;
}
int main()
{
while (1)
{
scanf("%d %d",&c,&n);
if (c==0&&n==0) return 0;
ans=0;
for (i=1;i<=n;i++)
{
ans+=qpow(c,gcd(n,i));
}
if (n%2==1)
{
ans+=n*qpow(c,(n+1)/2);
}
else
ans+=(n/2)*(qpow(c,n/2)+qpow(c,n/2+1));
ans/=2*n;
printf("%d\n",ans);
}
}