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.
The following figure shows all possible necklaces formed by 3 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
3 2 1
2 2 2
Sample output
6
11
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;
}