UVA 11255 Necklace(Burnside引理)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2222

题意:有三种不同颜色的珠子,白(W颗),灰(G颗),黑(B颗), 其中3<=W+G+B<=40,问用这些珍珠可以串成多少种(W+G+B)长的不同的项链(项链可在平面内转动,也可翻转)。

思路:令n=W+G+B,(1)旋转:想想,对于每一种置换,我们要找出在这种置换下哪些排列在置换后还是这样。旋转有n种情况,分别是旋转0,1,2……,n-1个。比如,旋转2,设n=12,那么所有的分成2组,每组6个。这两组要保持一样,那么WGB在每组中的个数和排列方式是一样的,此时必须WGB都是偶数才行,进而问题转化成W/2,G/2,B/2个在一组中的排列的个数有多少种(另一组跟这组的排列一样无需再计算),这就是一个简单的组合计算。因此,枚举n的约数i,k=n/Gcd(n,i),WGB都是k的倍数才可以,然后就是W/k、G/k、B/k的排列;(2)翻转:WGB中有0个奇数,绕对边的轴转和绕相对的顶点的轴转;有1个奇数,绕一个顶点一条边中点的轴转;有2个奇数,设WG为奇数,绕两个相对顶点的轴转,两个顶点分别是WG。





void init()

{

    int i,j;

    C[0][0]=1;

    FOR1(i,40)

    {

        C[i][0]=C[i][i]=1;

        FOR1(j,i-1) C[i][j]=C[i-1][j]+C[i-1][j-1];

    }

}





int Gcd(int x,int y)

{

    return !y?x:Gcd(y,x%y);

}





int x,y,z,n,T;



int main()

{

    init();

    RD(T);

    while(T--)

    {

        RD(x,y,z);

        n=x+y+z;

        int i,k;

        u64 ans=0;

        FOR1(i,n)

        {

            k=n/Gcd(n,i);

            if(x%k==0&&y%k==0&&z%k==0)

            {

                ans+=C[n/k][x/k]*C[(y+z)/k][y/k];

            }

        }

        int cnt=x%2+y%2+z%2;

        if(cnt==1)

        {

            if(x&1) ans+=C[n/2][(x-1)/2]*C[(y+z)/2][y/2]*n;

            else if(y&1) ans+=C[n/2][(y-1)/2]*C[(x+z)/2][x/2]*n;

            else ans+=C[n/2][(z-1)/2]*C[(x+y)/2][x/2]*n;

        }

        else if(cnt==0)

        {

            ans+=n/2*C[n/2][x/2]*C[(y+z)/2][y/2];

            if(x>=2) ans+=n/2*C[n/2-1][x/2-1]*C[(y+z)/2][y/2];

            if(y>=2) ans+=n/2*C[n/2-1][y/2-1]*C[(x+z)/2][x/2];

            if(z>=2) ans+=n/2*C[n/2-1][z/2-1]*C[(x+y)/2][x/2];

        }

        else if(cnt==2)

        {

            if(x%2==0) ans+=n*C[n/2-1][x/2]*C[(y+z-2)/2][(y-1)/2];

            else if(y%2==0) ans+=n*C[n/2-1][y/2]*C[(x+z-2)/2][(x-1)/2];

            else ans+=n*C[n/2-1][z/2]*C[(x+y-2)/2][(x-1)/2];

        }

        PR(ans/(2*n));

    }

    return 0;

}

  

你可能感兴趣的:(ide)