题意:
有k种颜色,每种颜色对应a[i]个球,球的总数不超过1000
要求第i种颜色的最后一个球,其后面接着的必须是第i+1种颜色的球
问一共有多少种排法
Sample test(s)
input
3 2 2 1
output
3
input
4 1 2 3 4
output
1680
Note
In the first sample, we have 2 balls of color 1, 2 balls of color 2, and 1 ball of color 3. The three ways for Kyoya are:
1 2 1 2 3 1 1 2 2 3 2 1 1 2 3
思路:
首先我们容易想到我们必须要确定每种颜色最后一个球的放法
所有对于最后一种颜色,假设这种颜色有b个球,而总球数为a
那么必然有一个球是放在最后一个位置的,那么剩下的球就是z=C(b-1,a-1)种方法
那么对于倒数第二种球,假设有x个,此时总球数位y=a-b
那么之前已经有z种方法了,而对于每一种放法,此时倒数第二种颜色拿出一个作为最后一个球的话,它对于每种放法必然只有一个固定方法,位置是最后一个没有放球的位置,这样既保证放法符合要求,而剩下的球就有C(x-1,y-1)种放法
然后相乘得到最后一种颜色与最后第二种颜色的方法,以此类推。。
可以使用费马小定理来优化组合数计算
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<stdlib.h> 5 #include<cmath> 6 using namespace std; 7 #define MOD 1000000007 8 #define ll long long 9 ll n; 10 ll a[1006]; 11 ll fac[1000006]; 12 ll pow_mod(ll a,ll i) 13 { 14 if(i==0) 15 return 1%MOD; 16 ll t=pow_mod(a,i/2); 17 ll ans=t*t%MOD; 18 if(i%2==1) 19 ans=ans*a%MOD; 20 return ans; 21 } 22 ll work(ll m,ll i) 23 { 24 return ( (fac[m]%MOD)* ( pow_mod(fac[i]*fac[m-i]%MOD ,MOD-2)%MOD))%MOD; 25 } 26 27 int main() 28 { 29 fac[0]=1; 30 for(int i=1;i<1000006;i++) 31 fac[i]=(fac[i-1]*i)%MOD; 32 ll ans=1; 33 ll sum=0; 34 scanf("%I64d",&n); 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%I64d",&a[i]); 38 sum+=a[i]; 39 } 40 for(int i=n;i>=1;i--) 41 { 42 ans=ans*work(sum-1,a[i]-1)%MOD; 43 sum-=a[i]; 44 } 45 printf("%I64d ",ans); 46 return 0; 47 }