UESTC 75 The Queen's New Necklaces

题意:一个项链的珠子的颜色有若干种。每种颜色的珠子个数为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,需要高精度,但是我比较懒,就没有打高精度的版本了。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int a[200005],n,m,p[200005];
 7 int gcd(int a,int b){
 8     if (b==0) return a;
 9     else return gcd(b,a%b);
10 }
11 int C(int n,int m){
12     int res=1;
13     for (int i=1;i<=n;i++) res*=i;
14     for (int i=1;i<=n-m;i++) res/=i;
15     for (int i=1;i<=m;i++) res/=i;
16     return res;
17 }
18 int main(){
19     int T,ans;
20     scanf("%d",&T);
21     while (T--){
22         scanf("%d",&m);n=0;
23         for (int i=1;i<=m;i++) {scanf("%d",&a[i]);n+=a[i];}
24         int ans=0;
25         for (int i=0;i<n;i++){
26             int num=gcd(i,n);
27             int K=n/num,tot=0;
28             p[0]=0;
29             bool pd=1;
30             for (int j=1;j<=m&&pd;j++){
31                 if (a[j]%K){
32                     pd=0;
33                 }else{
34                     p[++p[0]]=a[j]/K;
35                     tot+=a[j]/K;    
36                 }
37             }
38             if (!pd) continue;
39             for (int j=1;j<=p[0];j++)
40              ans+=C(tot,p[j]),tot-=p[j];
41         }
42         printf("%d
",ans/n);
43     }
44 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5528557.html