(带讲解)poj2409&poj1286 polya模板

这两道题一样啊,只是一个规定颜色个数,一个不规定罢了。

题解的话就讲2409这道题吧

题意:用m种颜色染长度为n的环,旋转和对称认为是同一种方案,求本质不同的方案数。

我们只要考虑出置换群G,直接套polya公式即可。

(polya定理公式及证明在我的另一篇博客里有详细说明)

首先,考虑一下旋转。

对于旋转,所有的节点都会旋转,所以循环节长度应该是一样的,这个长度是多长呢?

设每次转x格,现在在p号点,走k次后回到p点,即

p+kxp(%n)

kx0(%n)

所以kx模n等于0,即kx是n的倍数。

当然kx还是x的倍数,而k是循环节长度,要取最小,则满足以上两个条件的最小的kx是lcm(x,n)。

把lcm换成gcd

kx=nxgcd(x,n)

k=ngcd(x,n)

也就是说,循环节长度是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);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值