[ poj1286 ]Necklace of Beads(polya定理+组合计数)

传送门:http://poj.org/problem?id=1286


上次的Burnside引理后面提出的疑问,我们来说一下polya
这是polya的主要内容:

这里写图片描述
(来自百度百科)

我们可以发现polya和burnside求解的问题是一样的,都是求等价类的数目,但是burnside需要把所有的情况求出来,但是如果我们有循环节数和置换数就可以使用polya在很快的时间内求解。

那么对于这一题,颜色的数目是一定的(3种)
那么我们就只需要计算循环节。
对于旋转和翻转我们都要计算。
旋转:有n种置换,设旋转长度为i,则循环节长度为gcd(n,i)
翻转:奇数时,对称轴穿过珠子,一共n条。对称轴上的一个珠子构成一个循环,其他n-1个珠子分别以对称轴对称构成(n-1)/2个循环,所以循环节的个数是1+(n-1)/2=(n+1)/2 。
偶数时,对称轴可能穿过两个珠子,一共 n/2条,对称轴上的两个珠子构成两个循环,其他n-2个珠子分别以对称轴对称构成(n-2)/2个循环。还有一种情况,对称轴穿过两个珠子之间,这时候其他的珠子都两两对称,构成n/2个循环。
注意!同时考虑了旋转和翻转后,置换群的个数是2n。


code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll powmod(ll a,ll b)
{
    ll ans=1;
    while(b!=0)
    {
        if(b&1) ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}
int main()
{
    ll n,i,ans;
    while(scanf("%lld",&n)!=EOF)
    {
        if(n==-1) break;
        if(n==0){printf("0\n"); continue;}
        ans=0;
        for(int i=0;i<n;i++) ans+=powmod(3,gcd(n,i));

        if(n%2==1)
        {
            ans+=n*powmod(3,(n+1)/2);
        }
        else if(n%2==0)
        {
            ans+=(n/2)*powmod(3,n/2);
            ans+=(n/2)*powmod(3,(n-2)/2+2);
        }
        printf("%lld\n",ans/(n*2));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值