poj 2409解题报告
2011-01-29 16:35
288 查看
Let it Bead
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
![](http://poj.org/images/2409_1.jpg)
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
Sample Output
这道题,还有另一种方法就是直接套用polya公式,先生成所有的置换,每生成一种置换,然后计算每种置换的循环节数,最后通过公式求出来结果,这道题的关键是生成所有种类的置换,现在就主要讨论一下如何生成置换,因为旋转和翻转都是相同的,所以需要考虑旋转和翻转两种情况,选来看旋转的情况,任何一个项链都可以绕着它的中心旋转0个,1个,2个,..........,n-1个位置,在这样的变换下,各个点的编号换了位置,但形状和原形状相同,同样,顺时针旋转i个位置,等同于逆时针旋转n-i个位置,因此,所有这些旋转都可以用逆时针旋转来表示,于是,共有n个旋转,那么有位置0变到位置i的旋转课表示为:
0->i, 1->i+1,2->i+2,.......n-1->i+n-1,这里i是从0到n-1的。
然后说翻转,翻转一共分两种情况,n为奇数和n为偶数。
先看n为奇数的情况,一共有n中翻转,此时只有一种形式,即经过某个顶点i与中心的连线为轴的翻转:
i->i,i+1->i-1,i+2->i-2,.........(i+(n-1))%n->(i-(n-1)+n)%n
再看n为偶数的情况,在这里又分为了两种情况。
(1)这种是经过某个顶点i与中心的连线为轴的翻转,由于n为偶数,有对称性,所以此种共n/2种翻转:
i->i,i+1->i-1,i+2->i-2,.........(i+(n-1))%n->(i-(n-1)+n)%n
(2)这种是以顶点i和i+1的连线的中点与中心的连线为轴的翻转,同样,根据对称性,也有n/2种翻转:
i->i+1,i-1->i+2,i-2->i+3,..................(i-(n-1)+n)%n->(i+(n-1)+1)%n
所以给定长度n,共有2n种置换。下面是A了的代码
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2190 | Accepted: 1348 |
"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
![](http://poj.org/images/2409_1.jpg)
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计数经典问题,这道题出的太标准了,简直就是模板。下面的代码可以直接作为模板。
代码:
语言:c++
#include<iostream> using namespace std; int main() { int gcd(int a,int b); int c,s; while(cin>>c>>s) { if(c==0&&s==0) break; int k; long long p[64]; p[0]=1; for(k=0;k<s;++k) p[k+1]=p[k]*c; long long count=s&1?s*p[s/2+1]:(s/2)*(p[s/2]+p[s/2+1]); for(k=1;k<=s;++k) count+=p[gcd(k,s)]; count/=2*s; cout<<count<<endl; } return 0; } int gcd(int a,int b) { int c; if(a==0) return b; while(b!=0) { c=b; b=a%b; a=c; } return a; }[/code]
这道题,还有另一种方法就是直接套用polya公式,先生成所有的置换,每生成一种置换,然后计算每种置换的循环节数,最后通过公式求出来结果,这道题的关键是生成所有种类的置换,现在就主要讨论一下如何生成置换,因为旋转和翻转都是相同的,所以需要考虑旋转和翻转两种情况,选来看旋转的情况,任何一个项链都可以绕着它的中心旋转0个,1个,2个,..........,n-1个位置,在这样的变换下,各个点的编号换了位置,但形状和原形状相同,同样,顺时针旋转i个位置,等同于逆时针旋转n-i个位置,因此,所有这些旋转都可以用逆时针旋转来表示,于是,共有n个旋转,那么有位置0变到位置i的旋转课表示为:
0->i, 1->i+1,2->i+2,.......n-1->i+n-1,这里i是从0到n-1的。
然后说翻转,翻转一共分两种情况,n为奇数和n为偶数。
先看n为奇数的情况,一共有n中翻转,此时只有一种形式,即经过某个顶点i与中心的连线为轴的翻转:
i->i,i+1->i-1,i+2->i-2,.........(i+(n-1))%n->(i-(n-1)+n)%n
再看n为偶数的情况,在这里又分为了两种情况。
(1)这种是经过某个顶点i与中心的连线为轴的翻转,由于n为偶数,有对称性,所以此种共n/2种翻转:
i->i,i+1->i-1,i+2->i-2,.........(i+(n-1))%n->(i-(n-1)+n)%n
(2)这种是以顶点i和i+1的连线的中点与中心的连线为轴的翻转,同样,根据对称性,也有n/2种翻转:
i->i+1,i-1->i+2,i-2->i+3,..................(i-(n-1)+n)%n->(i+(n-1)+1)%n
所以给定长度n,共有2n种置换。下面是A了的代码
#include<iostream> #include<cmath> using namespace std; int main() { int c,s; double polya1(int c,int s); while(cin>>c>>s) { if(c==0&&s==0) break; cout<<polya1(c,s)<<endl; } return 0; } double polya1(int c,int s)//计算总数 { int polya(int *perm,int n,double &num);//计算每种置换的循环节 double x,t=0.0,m=c,n=s; int perm[100]; for(int i=0;i<=s-1;++i)//旋转的情况 { for(int j=0;j<=s-1;++j) perm[j]=(i+j)%s; polya(perm,s,x); t+=pow(m,x); } if(s%2==1)//翻转的情况 ,s长度s为奇数 { for(int i=0;i<=s-1;++i) { for(int j=0;j<=s-1;++j) perm[(i+j)%s]=(i-j+s)%s; polya(perm,s,x); t+=pow(m,x); } } else { for(int i=0;i<=(s/2-1);++i)//翻转的情况,长度s为偶数 { for(int j=0;j<=s-1;++j) perm[(i+j)%s]=(i-j+s)%s; polya(perm,s,x); t+=pow(m,x); for(int j=0;j<=s-1;++j) perm[(i-j+s)%s]=(i+j+1)%s; polya(perm,s,x); t+=pow(m,x); } } t/=(2*n); return t; } long long gcd(long long a,long long b) { if(a==0) return b; long long c; while(b!=0) { c=b; b=a%b; a=c; } return a; } int polya(int *perm,int n,double &num)//计算循环节数 { long long i,j,p,v[100]={0},ret=1; for(num=i=0;i<n;++i) if(!v[i]) { for(num++,j=0,p=i;!v[p=perm[p]];++j) v[p]=1; ret*=j/gcd(ret,j); } return ret; }
相关文章推荐
- POJ 1006解题报告
- POJ 1008解题报告
- POJ-1840 Eqs 解题报告
- Poj 2104 K-th Number 主席树 解题报告
- POJ 1008(映射) 解题报告
- poj 2001 解题报告
- POJ 1451 T9 [解题报告] Java
- 2011.11.1 poj1789 Truck History 解题报告
- 【解题报告】 POJ 2318 TOYS -- 判断点在某个梯形内 叉积 + 二分
- 解题报告:POJ_1833 排序
- poj解题报告——2676
- POJ 3074 解题报告
- POJ2112解题报告【网络流-初级-isap+floyd_warshall+二分】
- **POJ 1008 Maya Calendar解题报告
- poj解题报告——3273
- poj解题报告——poj 3536 Beer Refrigerator
- poj 1276 多重背包 解题报告
- POJ-1067 取石子游戏 解题报告
- POJ 1125 解题报告
- poj1579解题报告