HDU 1817 - Necklace of Beads【Polya定理】

Necklace of Beads
Time Limit: 1000MS   Memory Limit: 32768KB
Description:
Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 40 ). 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 


题意:
  用红色,蓝色,绿色三种颜色的N个珠子串成一个长度为N的项链,项链可以旋转和翻转,经过旋转和翻转所得的项链一样视为同一种项链,现在告诉你项链的长度S,求共能组成几条不同的项链.

算法分析:
  这个题目很明显是用Polya 定理解决这个计数问题,关键是分析群中置换的个数和每个置换的循环节个数.分析题目中出题目中所说的两种置换群:一种旋转置换和一种翻转置换,分别求出置换群的循环节个数即可以解决该题.
旋转置换:对于旋转置换群,群内置换的总个数显而易见是n个,因为是旋转置换,则置换的循环节长度为 gcd(i,n) (1<=i<=n).(注意:此结论仅适用于二维旋转置换)循环长度结论在《置换群的整幂运算中有详细推论讲解.
翻转置换:n的奇偶性会影响翻转置换置换的结果,因此得分奇偶讨论.翻转置换找循环节的关键是找出对称轴!
   当n为奇数,那么对称轴就是每个点和圆心的连线的延长线,共n条(如右图),很显然除了与圆心连线的点没有改变,其余点都跟对称的那个点置换了,所以循环节的个数是(n-1)/2+1.
   当n为偶数,那么对称轴有有种情况,一种为每个点和对面的点的连线,共n/2条(如左图),很显然除了对称轴上的两个点,其余点都跟对称的那个点置换了,所以循环节的个数是(n-2)/2+2,另外一种为两个相邻点中点和圆心的连线也是n/2条(如左图),显然每个点都跟对面的点置换了,循环节的个数是n/2.所以n为偶数时对称轴总共也是n条!


代码实现:
#include <iostream>
#include <stdio.h>
#include <string>
#include <math.h>
#include <string.h>
using namespace std;
typedef __int64 ll;
ll ans, sum;

ll pow(int a, int b)
{
    ll as = 1;
    for(int i = 0; i < b; i++)
        as *= a;
    return as;
}

int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}

ll solve(int n)
{
    sum = 0;
    if(n == 0)
        return 0;
    for(int i = 1; i <= n ;i++)///旋转置换
        sum += (ll)pow(3,gcd(i,n));
    if(n % 2 == 0)///翻转置换n为偶数
    {
        sum += (ll)pow(3,n/2+1)*n/2;
        sum += (ll)pow(3,n/2)*n/2;
    }
    else
        sum += (ll)pow(3,(n+1)/2)*n;
    ans = sum / (2 * n);
    return ans;
}


int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n == -1)
            break;
        printf("%I64d\n",solve(n));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值