poj 1286 Necklace of Beads 置换群polya计数
题目大意:
使用三种颜色珠子串成 一个n颗珠子的项链,项链旋转和翻转相同的视为同样方案,问有多少不同方案数
对于 群论中置换群的计算公式我们有 BurnSide 和 Polya
前者是找所有置换群,后者是找置换群循环因子,其两者公式也相差不远,因为 Polya计数 比较方便,所以通常使用 Polya公式
其中 ei 为第 i 个置换,其循环因子数量
对于 n 角/边对称图形, 其包括 旋转 和 反射
旋转顶点数量为 ( 0, 1, 2 ... n-1 ) : 循环因子数量: Gcd( n, i )
反射对于 偶数n 时,分为 n/2个顶点反射 与 n/2个边反射
顶点反射 循环因子数量: n/2+1
边反射 循环因子数量: n/2
对于 奇数n 时, 仅有 n个 顶点+边 反射
顶点+边 循环因子数量: n/2+1
解题代码:
View Code
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef long long LL; LL a[30]; int n; LL pow( LL x, int k ){ if( k == 0 ) return 1; LL res = pow( x, k/2 ); res = res*res; if( k&1 ) res *= x; return res; } int gcd(int a, int b) { return ( b == 0 ) ? a : gcd( b , a%b ); } int main(){ while( scanf("%d", &n) != EOF ) { if( !(~n) ) break; if( n == 0 ) printf("0\n"); else if( n == 1 ) printf("3\n"); else { LL res = pow(3,n); for(int i = 1; i < n; i++) res += pow(3, gcd(n,i) ); if( n&1 ) res += 1LL*(n)*( pow(3,n/2+1) ); else res += 1LL*(n/2)*( pow(3,n/2) + pow(3,n/2+1) ); res /= (n<<1); printf("%lld\n", res); } } return 0; }