uva11255 - Necklace 项链旋转翻转 置换

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 integers a, 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-9
using 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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值