CF 554C Kyoya and Colored Balls 组合数

题意: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 

令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;
} 


猜你喜欢

转载自blog.csdn.net/noone0/article/details/80012605