传送门
题目大意是给你三种颜色并给定相应的数量,请问能组成多少种不同的环(选择,对称同构)
Sample Input
2
3 2 1
2 2 2
Sample Output
6
11
颜色的个数类带有了限制,因为是对于环来说,所以其实还是比较好处理的
因为数量有了限制,所以不能单纯考虑置换的循环节的个数还要考虑循环节的长度。
先看旋转的情况,其实一直旋转后的置换的循环节的长度都是相等的。设:
num=gcd(i,n)
所以每个循环节的长度为:
len=nnum
设三个颜色的数量分别为 a、b、c ,只有:
a%len=0
b%len=0
c%len=0
同时满足才是一个可行分配,那有多少个呢?有
∑iCa/lennum∗Cb/lennum−a/len∗Cc/lennum−a/len−b/len
在看对称情况
如果n为奇数,那么循环节的情况是有 num=n−12 个长度为2的循环节和一个长度为 1 的循环节,置换个数有n个
这个又要和
Ca/2num∗Cb/2num−a/2∗Cc/2num−a/2−b/2∗n
如果为偶数,存在两种对称,点对称和边对称,点对称有 n2 个 num=n2−1 个长度为2的循环节和两个长度为1的循环节的置换,边对称有 n2 个 num=n2 个长度为2的循环节的置换
同样讨论 a、b、c 的奇偶,如果均为偶,两种对称数量是相等的,一起写为:
Ca/2num∗Cb/2num−a/2∗Cc/2num−a/2−b/2∗n
如果奇数的个数为2:那么他在边对称的情况下是不存在的,只有满足点对称:
Ca/2num∗Cb/2num−a/2∗Cc/2num−a/2−b/2∗2∗n2
涉及到大数,用java吧
import java.math.BigInteger;
import java.util.Scanner;
public class Main
{
static BigInteger fac[]=new BigInteger[45];
static void init()
{
fac[0]=BigInteger.valueOf(1);
for(int i=1;i<=40;i++)
fac[i]=fac[i-1].multiply(BigInteger.valueOf(i));
}
static BigInteger get(int n,int m)//获得组合数
{
return fac[n].divide(fac[m]).divide(fac[n-m]);
}
static int gcd(int a,int b)
{
return a%b==0?b:gcd(b,a%b);
}
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
init();
int t=sc.nextInt();
int a,b,c;
while(t-->0)
{
a=sc.nextInt();
b=sc.nextInt();
c=sc.nextInt();
int n=a+b+c;
BigInteger ans=new BigInteger("0");
for(int i=1;i<=n;i++)
{
int num=gcd(i,n);
int len=n/num;
if(a%len==0&&b%len==0&&c%len==0)
ans=ans.add(get(num,a/len).multiply(get(num-a/len,b/len).multiply(get(num-a/len-b/len,c/len))));
}
if((n&1)==1)
{
int odd=0;
if(a%2==1)
odd++;
if(b%2==1)
odd++;
if(c%2==1)
odd++;
if(odd==1)
{
int num=n/2;
BigInteger temp=get(num,a/2).multiply(get(num-a/2,b/2)).multiply(BigInteger.valueOf(n));
ans=ans.add(temp);
}
}
else
{
int odd=0;
if(a%2==1)
odd++;
if(b%2==1)
odd++;
if(c%2==1)
odd++;
if(odd==0)
{
int num=n/2;
BigInteger temp=get(num,a/2).multiply(get(num-a/2,b/2)).multiply(BigInteger.valueOf(n));
ans=ans.add(temp);
}
if(odd==2)
{
int num=n/2-1;
BigInteger temp=get(num,a/2).multiply(get(num-a/2,b/2)).multiply(BigInteger.valueOf(n));
ans=ans.add(temp);
}
}
System.out.println(ans.divide(BigInteger.valueOf(2*n)));
}
}
}