POJ 2409

Let it Bead

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6980   Accepted: 4629

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

Source

Ulm Local 2000

大致题意:

给定M种颜色的珠子,每种颜色珠子的个数均不限,将这些珠子做成长度为N的项链。

问能做成多少种不重复的项链,最后的结果不会超过int类型数据的表示范围。并且两

条项链相同,当且仅当两条项链通过旋转或是翻转后能重合在一起,且对应珠子的颜

色相同。

解题思路:

使用polya定理

首先了解一下集合,置换等概念

https://blog.csdn.net/xuzengqiang/article/details/7476671

然后具体看polya定理的公式

Polya定理:设 G = {a1,a2,…,ag}是 N 个对象的置换群,用 M 种颜色给这 N 个

对象着色,则不同的着色 方案数为:

                  |G|^(-1) * {M^c(a1) + M^c(a2) + … + M^c(ag)}。

其中 c(ai)为置换 ai 的循环节数,( i = 1,2,…,g )。

对于这道题,直接用Polya定理求解,找出所有的置换,并求出置换的循环节数。然后

根据上边公式求出 M^c(ai) 的总和,再除以置换群个数。

题中有两种置换方式:

1.旋转置换。

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

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

p+kx≡p(%n)
kx≡0(%n)
所以kx模n等于0,即kx是n的倍数。

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

把lcm换成gcd

kx=nx/gcd(x,n)
k=n/gcd(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种置换。

2.翻转置换。根据 N 的奇偶性分情况讨论。

N为奇数时:

       以第 i 个珠子为顶点和中心翻转,翻转后,第 i 个珠子保持不变,其余珠子两两相

互对换,因为有 N 个珠子,所以有 N 种翻转置换,每种翻转循环节数为 (N+1) / 2。

N为偶数时,有两种翻转方式:

      以两边相对的两个珠子为轴和中心翻转,翻转后,这两个珠子保持不变,其余珠子

两两相互对换,共有 N/2 种翻转置换,每种翻转循环节数为 (N+2) / 2。

      以相邻的珠子中间连线为轴和中心翻转,翻转后,所有珠子两两相互对换,共有 N/2

种翻转置换,每种翻转循环节数为 N/2。

然后根据Polya定理的公式和上述所求求出结果。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
 
int M,N;
 
int GCD(int a,int b)
{
    if(b == 0)
        return a;
    return GCD(b,a%b);
}
 
int main()
{
    while(~scanf("%d%d",&M,&N) && (M||N))
    {
        int sum = 0;
        for(int i = 1; i <= N; ++i)
        {
            int tmp = GCD(N,i);
            sum += (int)(pow(M*1.0,tmp*1.0));
        }
        if(N & 1)
            sum += (int)(N * pow(M*1.0, (N+1)/2.0));
        else
        {
            sum += (int)((N/2) * pow(M*1.0, (N+2)/2.0));
            sum += (int)((N/2) * pow(M*1.0, N/2.0));
        }
        sum = sum/(2*N);
        printf("%d\n",sum);
    }
 
    return 0;
}
发布了158 篇原创文章 · 获赞 34 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_40421671/article/details/95492263
POJ