Kyoya Ootori has a bag with n colored balls that are colored with k different
colors. The colors are labeled from 1 to k.
Balls of the same color are indistinguishable. He draws balls from the bag one by one until the bag is empty. He noticed that he drew the last ball of color ibefore
drawing the last ball of color i?+?1 for all i from 1 to k?-?1.
Now he wonders how many different ways this can happen.
Input
The first line of input will have one integer k (1?≤?k?≤?1000)
the number of colors.
Then, k lines will follow. The i-th
line will contain ci,
the number of balls of the i-th color (1?≤?ci?≤?1000).
The total number of balls doesn‘t exceed 1000.
Output
A single integer, the number of ways that Kyoya can draw the balls from the bag as described in the statement, modulo 1?000?000?007.
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
题意:
有k种颜色,每种颜色对应a[i]个球,球的总数不超过1000
要求第i种颜色的最后一个球,其后面接着的必须是第i+1种颜色的球
问一共有多少种排法
思路:
首先我们容易想到我们必须要确定每种颜色最后一个球的放法
所有对于最后一种颜色,假设这种颜色有b个球,而总球数为a
那么必然有一个球是放在最后一个位置的,那么剩下的球就是z=C(b-1,a-1)种方法
那么对于倒数第二种球,假设有x个,此时总球数位y=a-b
那么之前已经有z种方法了,而对于每一种放法,此时倒数第二种颜色拿出一个作为最后一个球的话,它对于每种放法必然只有一个固定方法,位置是最后一个没有放球的位置,这样既保证放法符合要求,而剩下的球就有C(x-1,y-1)种放法
然后相乘得到最后一种颜色与最后第二种颜色的方法,以此类推。。
可以使用费马小定理来优化组合数计算
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define LL long long const LL mod = 1000000007; LL n; LL a[1005]; LL fac[1000005]; LL ppow(LL a,LL b) { LL c=1; while(b) { if(b&1) c=c*a%mod; b>>=1; a=a*a%mod; } return c; } LL work(LL m,LL i) { return ((fac[m]%mod)*(ppow((fac[i]*fac[m-i])%mod,mod-2)%mod))%mod; } int main() { LL i,j,k; fac[0] = 1; for(i = 1; i<1000005; i++) fac[i]=(fac[i-1]*i)%mod; LL ans = 1,sum = 0; scanf("%I64d",&n); for(i = 1; i<=n; i++) { scanf("%I64d",&a[i]); sum+=a[i]; } for(i = n; i>=1; i--) { ans*=work(sum-1,a[i]-1); ans%=mod; sum-=a[i]; } printf("%I64d\n",ans); return 0; }