poj1286
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7733 | Accepted: 3234 |
Description
![](http://poj.org/images/1286_1.jpg)
Input
-1 denotes the end of the input file.
Output
Sample Input
4 5 -1
Sample Output
21 39
Source
译文:
项链的珠子
描述:
红色、蓝色或绿色的珠子被连接在一起,成一个圆形项链的n个珠子(n < 24)。如果重复所产生的旋转周围的圆形项链或反射轴的对称轴都被忽视,有多少不同的形式的项链有吗?
输入:
输入有若干行,每行包含输入数据, - 1表示输入文件的结束。
输出:
应包含输出数据:不同形式的数,在每行对应于输入数据。
样例输入:
4
5
-1
样例输出:
21
39
题解:
虽然是裸的Pólya定理,但属于组合数学的内容,还是少不了自我扫盲。Pólya定理的基础Burnside引理是求解互异的组合状态的个数的方法:
据说该定理的应用比较麻烦,染色问题常用Pólya定理:
其中G={a1 ,…ag} c(ai )为置换gi的循环节数(i=1…s)。
对应题目的翻转问题,分奇偶讨论。
奇数时,如题图右,对称轴是一个珠子到圆心的连线,一共n条。选定对称轴后,对称轴上的一个珠子构成一个循环,其他n-1个珠子分别以对称轴对称构成(n-1)/2个循环,所以循环节的个数是 1 + (n – 1) / 2 = (n + 1) / 2 。
偶数时,如题图左,对称轴可能是两个珠子的连线,一共 n / 2条。选定对称轴后,对称轴上的两个珠子构成两个循环,其他n-2个珠子分别以对称轴对称构成(n-2)/2个循环;对称轴还可能是两个珠子的中点和圆心的连线,所有珠子两两对称,构成n / 2 个循环。
对应题目的旋转问题,直接套用现成结论。
一共n个置换,第i个置换的循环节的个数为gcd(n, i)。证明详见《挑战程序设计竞赛(第2版)》P302:
有了循环节,接下来只要将循环节数c作为幂求mc即可。值得注意的是,同时考虑了旋转和翻转后,置换群的个数应当是2n。
AC代码:(数据太水了,不用任何优化也能A)
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ll long long int main(){ int n; while(scanf("%d",&n)==1){ if(n==-1) break; if(!n){puts("0");continue;} ll ans=0; for(int i=1;i<=n;i++) ans+=pow(3.0,__gcd(n,i)); if(n&1) printf("%lld\n",(ans+(ll)pow(3.0,1+n/2)*n)/(n*2)); else printf("%lld\n",(ans+(ll)pow(3.0,n/2)*(n/2)+(ll)pow(3.0,2+(n-2)/2)*(n/2))/(n*2)); } return 0; }
---------------------------------------------------------------------------
Polya定理:
L=1/|G|*(m^c(p1)+m^c(p2)+...+m^c(pk))
G为置换群大小
m为颜色数量
c(pi)表示第i个置换的循环节数
如置换(123)(45)(6)其循环节数为3