POJ1286-Necklace of Beads(Polya模板题)

9 篇文章 0 订阅
3 篇文章 0 订阅

Necklace of Beads
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 8930 Accepted: 3709
Description

Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 24 ). If the repetitions that are produced by rotation around the center of the circular necklace or reflection to the axis of symmetry are all neglected, how many different forms of the necklace are there?

Input

The input has several lines, and each line contains the input data n.
-1 denotes the end of the input file.
Output

The output should contain the output data: Number of different forms, in each line correspondent to the input data.
Sample Input

4
5
-1
Sample Output

21
39
题目:POJ1286
题意:给你一个n,表示你有n种颜色的珠子,并且要把n个珠子串成一个手镯,问你有多少种方案,旋转,翻转相同的算一种方案。
思路:裸的Polya计数+翻转情况的考虑。
对于翻转,有两种情况:
n为奇数: 考虑一个最简单的正三角形,它的对称轴只有一种,即顶点到对边的中点的连线,假设对称轴为顶点1到其对边中点的连线,翻转后2与3顶点重合,1与自身重合,若翻转后相同,那么说明2与3的颜色相同,1与1的颜色相同(废话)。即可把(2,3)看作一个点,(1)看作1个点,也就是两个循环节,方案数为:n*c^(n/2+1)
n为偶数: 考虑一个正四边形,他的对称轴有两种,顶点到对顶点的连线,有n/2条,循环节n/2+1个。另一种为边到对边中点的连线,有n/2条,循环节n/2个。总的方案数为:(n/2)*(c^(n/2+1)+c^(n/2))
那么不管是奇数边还是偶数边,都有n个置换,根据Polya定理,加上旋转的n个置换,最终的答案要除以2n。
AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#define met(s,k) memset(s,k,sizeof s)
#define scan(a) scanf("%d",&a)
#define scanl(a) scanf("%lld",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannl(a,b) scanf("%lld%lld",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define prin(a) printf("%d\n",a)
#define prinl(a) printf("%lld\n",a)
using namespace std;
typedef long long ll;
const ll maxn=46400;
ll gcd(ll a,ll b)
{
    if(a<b)swap(a,b);
    if(b==0)return a;
    return gcd(b,a%b);
}
ll ksm(ll x,ll y)
{
    ll res=1;
    while(y)
    {
        if(y%2)res*=x;
        x*=x;
        y/=2;
    }
    return res;
}
int main()
{
    ll n;
    while(scanl(n),n!=-1)
    {
        ll ans=0;
        if(n==0)
        {
            prin(0);
            continue;
        }
        for(int i=1;i<=n;i++)ans+=ksm(3,gcd(n,i));
        if(n&1)ans+=n*ksm(3,n/2+1);
        else ans+=n*((double)ksm(3,n/2)/2+(double)ksm(3,n/2+1)/2);
        prinl(ans/(2*n));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值