POJ-2409 Let it Bead 【置换群-Polya定理】

Let it Bead

Time Limit: 1000MS   Memory Limit: 65536K

Description

"Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. As you can deduce from the company name, their business is beads. Their PR department found out that customers are interested in buying colored bracelets. However, over 90 percent of the target audience insists that the bracelets be unique. (Just imagine what happened if two women showed up at the same party wearing identical bracelets!) It's a good thing that bracelets can have different lengths and need not be made of beads of one color. Help the boss estimating maximum profit by calculating how many different bracelets can be produced. 

A bracelet is a ring-like sequence of s beads each of which can have one of c distinct colors. The ring is closed, i.e. has no beginning or end, and has no direction. Assume an unlimited supply of beads of each color. For different values of s and c, calculate the number of different bracelets that can be made.

Input

Every line of the input file defines a test case and contains two integers: the number of available colors c followed by the length of the bracelets s. Input is terminated by c=s=0. Otherwise, both are positive, and, due to technical difficulties in the bracelet-fabrication-machine, cs<=32, i.e. their product does not exceed 32.

Output

For each test case output on a single line the number of unique bracelets. The figure below shows the 8 different bracelets that can be made with 2 colors and 5 beads.

Sample Input

1 1
2 1
2 2
5 1
2 5
2 6
6 2
0 0

Sample Output

1
2
3
5
8
13
21



题目大意:给你c中颜色,s长度的项链,问有多少种本质不同的染色方案(可通过旋转,翻转得到的为同一种)。
很显然这题要用到置换群的相关知识,而很显然这题如果一个一个找不动点的话很麻烦,我们直接找循环节数就好了,然后用Polya定理一波带走。。

首先对于旋转,很明显其置换群的元素|G|=n(有n种置换)分别为步长为1到n的置换,举个例子,对于项链长度为4的时候:
1 2
3 4
旋转步长为1,那么循环节数为1:(1,2,4,3)
步长为2,循环节数为2:(1,4)(2,3)
步长为3,循环节数为1:(1,3,4,2)
步长为4,循环节数为4:(1)(2)(3)(4)

我们可以知道步长为i时循环节长度为LCM(n,i)/i,那么其循环节节数为n/(LCM(n,i)/i),即gcd(n,i)
那么对于步长为i的一种置换,其方案数为c^gcd(n,i)

接下来就是翻转了,翻转分奇数偶数:
当n为奇数的时候:

选择1个顶点,划开两边,则有n个顶点,即n种置换,每种置换有n/2+1个循环节,如上图:设1为顶点,即循环节为:(1)(2,3)

当n为偶数的时候,又分为2种情况:

对于第一种情况没有不动点,那么循环节数为n/2,有n/2种翻转(即沿(1,2)翻转,沿(1,3)翻转...)
对于第二种情况又两个不动点,那么循环节数为(n-2)/2+2=(n+2)/2,也有n/2种翻转。

那么根据Polya定理就可以愉快地得出答案了。
以下是AC代码:
#include <cstdio>
#include <algorithm>
using namespace std;

int qick(int a,int b)
{
    int ans=1;
    while (b){
        if (b&1) ans=ans*a;
        a*=a;
        b>>=1;
    }
    return ans;
}

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

int main()
{
    int c,n;
    while (scanf ("%d%d",&c,&n)){
        if (c==0 && n==0) break;
        int ans=0;
        for (int i=1; i<=n; i++){
            ans+=qick(c,gcd(n,i));
        }
        if (n&1) ans+=qick(c,(n+1)/2)*n;
        else ans+=qick(c,n/2)*n/2+qick(c,(n+2)/2)*n/2;
        printf ("%d\n",ans/(n*2));
    }
    return 0;
}


猜你喜欢

转载自www.cnblogs.com/lonely-wind-/p/12186739.html