uva11255 - Necklace 项链旋转翻转 置换

来源:互联网 发布:流行朋克知乎 编辑:程序博客网 时间:2023/09/28 02:03

Problem C - Necklace


Once upon a time, three girls - Winnie, Grace and Bonnie - owned a large number of pearls. However, each of them only had a single color of pearls. Winnie had white pearls, Grace had grey pearls and Bonnie had black pearls. One day, after a long discussion, they decided to make necklaces using the pearls. They are interested in knowing how many patterns can be formed using a certain number of pearls of each color, and have asked you to solve this problem for them.

Note that rotating or flipping over a necklace cannot produce a different kind of necklace. i.e. The following figure shows three equivalent necklaces.

Rotating and turning over a necklace


The following figure shows all possible necklaces formed by 3 white pearls, 2 grey pearls and 1 black pearl.

All necklaces formed by3 white pearls, 2 grey pearls and 1 black pearl


Input
The input begins with an integer N ( 2500) which indicates the number of test cases followed. Each of the following test cases consists of three non-negative integersa,b, c, where 3 a +b + c 40.

Output
For each test case, print out the number of different necklaces that formed by a white pearls, b grey pearls and c black pearls in a single line.

Sample input
2
3 2 1
2 2 2

Sample output
6
11

  有三种颜色的珠子,能组成多少种项链,旋转翻转算一种。

  设珠子编号0-n。

  旋转:如果逆时针旋转i颗珠子的间距,则珠子0,i,2i...构成一个循环。循环节n/gcd(i,n),有gcd(i,n)个这样的循环。

  翻转:当n为奇数,对称轴有n条,每条对称轴形成(n-1)/2个长度为2的循环和1个长度为1的循环。当n为偶数,有两种对称轴。穿过珠子的对称轴有n/2条,各形成n/2-1个窗独为2的循环和2个长度为1的循环。不穿过珠子的对称轴有n/2条,各形成n/2个长度为2的循环。

  这里每种颜色的珠子不是无穷的,因为一个循环中要用同一种颜色,所以还要判断是否满足。

 

#include<iostream>#include<algorithm>#include<queue>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<set>#include<map>#define INF 0x3f3f3f3f#define MAXN 45#define MAXM 1500#define MOD 1000000007#define MAXNODE 8*MAXN#define eps 1e-9using namespace std;typedef long long LL;int T;LL C[MAXN][MAXN];void getC(){    for(int i=0;i<MAXN;i++){        C[i][0]=C[i][i]=1;        for(int j=1;j<i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1];    }}int gcd(int a,int b){    return a%b?gcd(b,a%b):b;}LL cal(int a,int b,int c,int l,int m){    if(a<0||b<0||c<0) return 0;    if(a%l||b%l||c%l) return 0;    a/=l;    b/=l;    return C[m][a]*C[m-a][b];   //从m个循环中选a个用颜色a,从剩下的中选b个用颜色b,再剩下的用颜色c}int main(){    freopen("in.txt","r",stdin);    getC();    scanf("%d",&T);    while(T--){        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        int n=a+b+c;        LL ans=0;        //旋转        for(int i=0;i<n;i++){            int l=gcd(i,n);            ans+=cal(a,b,c,n/l,l);        }        //翻转        //n为奇数,分别选一种颜色的珠子穿过对称轴,这个珠子可以有n个位置        if(n%2){            ans+=cal(a-1,b,c,2,n/2)*n;            ans+=cal(a,b-1,c,2,n/2)*n;            ans+=cal(a,b,c-1,2,n/2)*n;        }        //n为偶数        else{            ans+=cal(a,b,c,2,n/2)*(n/2);    //对称轴不穿过珠子,有n/2种对称轴            //对称轴穿过2种颜色珠子,有n种对称轴            ans+=cal(a-1,b-1,c,2,n/2-1)*n;            ans+=cal(a-1,b,c-1,2,n/2-1)*n;            ans+=cal(a,b-1,c-1,2,n/2-1)*n;            //对称轴穿过2个同样颜色的珠子,有n/2种对称轴            ans+=cal(a-2,b,c,2,n/2-1)*(n/2);            ans+=cal(a,b-2,c,2,n/2-1)*(n/2);            ans+=cal(a,b,c-2,2,n/2-1)*(n/2);        }        printf("%lld\n",ans/(2*n));    }    return 0;}



0 0