POJ 2409 Let it Bead【polya 计数法,burnside定理】


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;
}
posted @ 2011-02-16 16:23  AndreMouche  阅读(618)  评论(0编辑  收藏  举报