题意:一个项链的珠子的颜色有若干种。每种颜色的珠子个数为Ai。求有多少种不同的项链?
我们考虑,如果旋转i个珠子,那么会产生gcd(n,i)个循环节,每个循环节的大小我们假设为K,那么如果有一个颜色的数量不是K的倍数,那么必然没有置换过后等价的情况,然而,如果全部都是K的倍数,那么我们就相当于在gcd(n,i)个空位里面,每种颜色放入a[i]/K个的方案总数,这是一个简单的组合计数问题,方法大概就是c(n,m1)*c(n-m1,m2)*c(n-m1-m2,m3)*... ...,然后还要再除以n,由于这题n高达1000,需要高精度,但是我比较懒,就没有打高精度的版本了。
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
int a[],n,m,p[];
int gcd(int a,int b){
if (b==) return a;
else return gcd(b,a%b);
}
int C(int n,int m){
int res=;
for (int i=;i<=n;i++) res*=i;
for (int i=;i<=n-m;i++) res/=i;
for (int i=;i<=m;i++) res/=i;
return res;
}
int main(){
int T,ans;
scanf("%d",&T);
while (T--){
scanf("%d",&m);n=;
for (int i=;i<=m;i++) {scanf("%d",&a[i]);n+=a[i];}
int ans=;
for (int i=;i<n;i++){
int num=gcd(i,n);
int K=n/num,tot=;
p[]=;
bool pd=;
for (int j=;j<=m&&pd;j++){
if (a[j]%K){
pd=;
}else{
p[++p[]]=a[j]/K;
tot+=a[j]/K;
}
}
if (!pd) continue;
for (int j=;j<=p[];j++)
ans+=C(tot,p[j]),tot-=p[j];
}
printf("%d\n",ans/n);
}
}