POJ 2409 Let it Bead
算法核心:polya 计数法,burnside定理
http://blog.sina.com.cn/s/blog_6f71bea30100opru.html
大意:
珠子的颜色有c种,问可组成多少种长度为s的项链?
分两种情况讨论:
旋转:
n种旋转方法每种旋转i个格(1<=i<=n)循环结有gcd(i,n)个
翻转:
(1)这种是经过某个顶点i与中心的连线为轴的翻转,由于n为偶数,有对称性,所以此种共n/2种翻转:
(2)这种是以顶点i和i+1的连线的中点与中心的连线为轴的翻转,同样,根据对称性,也有n/2种翻转:
所以给定长度n,共有2n种置换。
#include<stdio.h> #include<string.h> const int N = 35; bool prime[N]; void init() { int i,j; memset(prime,true,sizeof(prime)); for(i=2;i<N;i++) { if(prime[i]) { for(j=i+i;j<N;j+=i) prime[j]=false; } } } int pow(int a,int b) { int ans = 1; while(b--)ans=ans*a; return ans; } int gcd(int a,int b) { int r; if(a>b) { r=a;a=b;b=r; } while(a) { r=b%a; b=a; a=r; } return b; } int main() { int c,s; init(); while(scanf("%d%d",&c,&s)!=EOF) { if(c==0&&s==0)break; if(s==0||c==0) { printf("0\n"); continue; } int ans = 0; if(prime[s]) { ans = pow(c,s); ans=ans+(s-1)*c; } else { ans = pow(c,s); int i; for(i=1;i<s;i++) { ans=ans+pow(c,gcd(i,s)); } } int cur = s; if(s&1)//奇数 { ans=ans+s*pow(c,s/2+1); cur=cur+s; } else { ans=ans+s/2*pow(c,s/2)+s/2*pow(c,s/2+1); cur=cur+s; } printf("%d\n",ans/cur); } return 0; }