题意:n种颜色的小球,第i个颜色的球有c[i]个.
规则:颜色i的最后一个球必须在颜色i+1最后一个的前面.[i=1..k-1].(也就是颜色i+1不能比颜色i先放完)
n,c[i]<=1000.总的球个数<=1000,问有多少种合法的放法?
假如已经放好前i种颜色,现在插入第i种颜色.
显然最后一位置放第i种颜色,然后剩下c[i]-1个元素插入前面m=pre[i-1]+1个位置中即可.
有重复选择的组合x1+x2+...xm=c[i]-1
规则:颜色i的最后一个球必须在颜色i+1最后一个的前面.[i=1..k-1].(也就是颜色i+1不能比颜色i先放完)
n,c[i]<=1000.总的球个数<=1000,问有多少种合法的放法?
假如已经放好前i种颜色,现在插入第i种颜色.
显然最后一位置放第i种颜色,然后剩下c[i]-1个元素插入前面m=pre[i-1]+1个位置中即可.
有重复选择的组合x1+x2+...xm=c[i]-1
令yi=xi+1 -> y1+y2+..ym=c[i]-1+m=tot.然后从tot-1个间隔中选m-1个:C(tot-1,m-1).
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e3+5,mod=1e9+7; int n,K,c[N],pre[N]; ll f[N]; ll powmod(ll x,ll n) { ll s=1; while(n) { if(n&1) s=(s*x)%mod; n>>=1; x=(x*x)%mod; } return s; } ll C(int n,int m) { ll a=f[n],b=(f[n-m]*f[m])%mod; return (a*powmod(b,mod-2))%mod; } int main() { ios::sync_with_stdio(false); cin.tie(0); f[0]=1; for(int i=1;i<N;i++) f[i]=(f[i-1]*i)%mod; cin>>K; for(int i=1;i<=K;i++) cin>>c[i],pre[i]=pre[i-1]+c[i]; ll res=1; for(int i=2;i<=K;i++) { //x1+x2+..xm=c[i]-1 //y1+y2...ym=c[i]-1+m int m=pre[i-1]+1; int tot=c[i]-1+m-1,r=m-1; res=(res*C(tot,r))%mod; } cout<<res<<'\n'; return 0; }