题目链接:http://acm.uestc.edu.cn/problem.php?pid=1153
题意:一个项链的珠子的颜色有若干种。每种颜色的珠子个数为Ai。求有多少种不同的项链?
思路:Burnside定理的描述是:
对于本题,G就是旋转0、1、2……n-1。那么我们需要计算旋转i时的不变元个数。对于旋转0度,是经典的排列组合的问题,即有可重复元素出现的排列问题.然后旋转i格,共有Gcd(n,i)个循环,每个循环中有N=n/gcd(n,i)个元素 (n表示小珠子总个数)。如果对于某种颜色的小珠子,它的个数不是N的整数倍,那么显然这种旋转下不存在不动点。如果存在,那么相当于A[i]/N个新的同颜色的小球拿去重新组成一个环的种类数,同样是上面的经典问题。如下图所示,n=10,i=5,三种小球,个数分别为2,4,4,则下面一种排列是不变元:
import java.io.*;
import java.util.*;
import java.math.*;
import java.text.*;
public class Main
{
static int Gcd(int a,int b)
{
return b==0?a:Gcd(b,a%b);
}
public static void main(String args[])
{
Scanner cin=new Scanner(System.in);
BigInteger f[]=new BigInteger[1005],ans,temp;
int C;
int i,j,k,tot,sum,n,a[]=new int[105],b[]=new int[105];
f[0]=BigInteger.ONE;
for(i=1;i<=1000;i++) f[i]=f[i-1].multiply(BigInteger.valueOf(i));
C=cin.nextInt();
while(C-->0)
{
n=cin.nextInt();
sum=0;
for(i=1;i<=n;i++)
{
a[i]=cin.nextInt();
sum+=a[i];
}
ans=f[sum];
for(i=1;i<=n;i++) ans=ans.divide(f[a[i]]);
for(i=1;i<sum;i++)
{
k=sum/Gcd(sum,i);
tot=0;
for(j=1;j<=n;j++)
{
if(a[j]%k!=0) break;
b[j]=a[j]/k;
tot+=b[j];
}
if(j<=n) continue;
temp=f[tot];
for(j=1;j<=n;j++) temp=temp.divide(f[b[j]]);
ans=ans.add(temp);
}
System.out.println(ans.divide(BigInteger.valueOf(sum)));
}
}
}