http://codeforces.com/contest/554/problem/C
题意 可看作
给m个颜色的气球,每种颜色有一定数量(至少为1)
然后构造 出 第k个颜色的气球后面不存在有比k小的颜色的气球存在。。。的方案数
正向构造毕竟麻烦,最最后一个入手比较简单、
气球总是为sum、第i种颜色气球有a[i]个
最后一个肯定是第K个颜色,因为序列长度固定为sum,所以第k个颜色摆放方案是C(sum-1,a[k]-1);
接下来的第k-1个颜色气球的最后一个一定是放在最接近 最后一个k的位置(否则如果最接近最后一个k的位置放了 比k-1还小的数,就不符合题意了)
所以第k-1个颜色的气球方案数为 C(sum-a[k]-1,a[k-1]-1);
以此类推
。。
因为组合数太大,,,并且给出的模恰好为素数。。所以直接用费马小定理+快速幂就好了。。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
int tm[1005];
const __int64 mod =1000000007;
__int64 fast_m(__int64 a,__int64 b)
{
__int64 x,ans=1;
x=a;
while(b)
{
if (b&1)
ans=(ans*x)%mod;
x=(x*x)%mod;
b/=2;
}
return ans;
}
__int64 n;
__int64 fac[1000010];
__int64 cal(__int64 x,__int64 y)
{
__int64 ans=1;
ans*=(fac[x]*fast_m(fac[y]*fac[x-y]%mod,mod-2))%mod;
//(a/b)%mod,等价于(a*b^(mod-2))%mod mod必须为素数
return ans;
}
int main()
{
__int64 i;
fac[0]=1;
for( i=1;i<=1000000;i++)
fac[i]=fac[i-1]*i%mod;
scanf("%I64d",&n);
__int64 sum=0;
for(i=1;i<=n;i++)
{
scanf("%I64d",&tm[i]);
sum+=tm[i];
}
__int64 ans=1;
for(i=n;i>=1;i--)
{
ans*=cal(sum-1,tm[i]-1);
ans%=mod;
sum-=tm[i];
}
printf("%I64d\n",ans);
return 0;
}