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;

}

你可能感兴趣的:(ide)