Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7082 | Accepted: 2952 |
Description
Input
Output
Sample Input
4 5 -1
Sample Output
21 39
题目意思: 给出红,绿,蓝3种颜色 的n个珠子,求能够组成多少个不同的项链。 (旋转 和 翻转后 相同的属于同一个项链)
Polya定理: (1)设G是p个对象的一个置换群,用k种颜色给这p个对象,若一种染色方案在群G的作用下变为另一种方案,则这两个方案当作是同一种方案,这样的不同染色方案数为
(2)对于N个珠子的项链,共有n种旋转置换和n种翻转置换。
对于旋转置换:每种置换的循环节数c(fi) = gcd(n,i),(i为一次转过多少个珠子)
对于翻转置换:如果n为奇数,共有n种翻转置换,每种置换的循环节数均为c(f) = n/2 + 1; 如果n为偶数,分两种情况 <1> 从空白处穿对称轴,则轴两边各有n/2个对象,得到c(f) = n/2;
<2> 从两个对象上穿对称轴,则轴两边各有n/2-2个对象,得到c(f) = n/2 + 1。
代码:注意n为0的情况
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define LL long long using namespace std; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } int main() { int n, i; LL ans; while(scanf("%d", &n), n != -1) { if(n == 0) { printf("0\n"); continue; } ans = 0; /*n次旋转*/ for(i = 1; i <= n; i++) ans += pow(3.0, gcd(n, i)); /*n次翻转*/ ans += n&1?n*pow(3.0, n/2+1):n*pow(3.0, n/2)/2+n*pow(3.0, n/2+1)/2; ans /= 2*n;//共2*n个置换 printf("%lld\n", ans); } return 0; }