您的位置:首页 > 其它

Necklace UVA - 11255(polya计数)

2017-09-08 16:40 323 查看
传送门

题目大意是给你三种颜色并给定相应的数量,请问能组成多少种不同的环(选择,对称同构)

Sample Input

2

3 2 1

2 2 2

Sample Output

6

11

颜色的个数类带有了限制,因为是对于环来说,所以其实还是比较好处理的

因为数量有了限制,所以不能单纯考虑置换的循环节的个数还要考虑循环节的长度。

先看旋转的情况,其实一直旋转后的置换的循环节的长度都是相等的。设:num=gcd(i,n)

所以每个循环节的长度为:len=nnum

设三个颜色的数量分别为a、b、c,只有:a%len=0b%len=0c%len=0同时满足才是一个可行分配,那有多少个呢?有∑iCa/lennum∗Cb/lennum−a/len∗Cc/lennum−a/len−b/len

在看对称情况

如果n为奇数,那么循环节的情况是有num=n−12个长度为2的循环节和一个长度为1的循环节,置换个数有n个

这个又要和a、b、c的奇偶有关如果abc全为奇数,那不存在,如果恰好只有一个奇数,把那个奇数减1,则有: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
.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)));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: