题目大意
有m个教室,第i个教室最多能容纳Yi组人,初始时第i个教室有Xi组人。
现在每组人要从当前所在的教室a移动到教室b(a≤b)。我们不知道第i组人初始在哪间教室,以及它要去哪间教室,求可能的方案数。答案对
109+7
取模
数据范围
1≤m≤100 0< ∑Xi ≤1000 0≤Xi,Yi≤100
思路
设s[i]=
∑ij=1xj
先无视每个组的编号,然后设f[i][j]为初始前i个教室,已经分配了j组人的新教室,方案数为多少。转移显然:
f[i][j]=∑f[i−1][j−k]∗ Cks[i]−(j−k)
其中k枚举的是放在教室i的组数,注意0≤k≤Y[i]。
那么f[m][s[m]]就是要求的答案了。加上每组人编号的影响:
ans=f[m][s[m]]∗∏i=1m∗ CX[i]s[m]−s[i−1]
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mo=1e9+7;
int n,m,s[105],f[105][1005],Fact[1005],Ie[1005],X[105],Y[105];
int quick(int x,int y)
{
if (!y) return 1;
int tmp=quick(x,y/2);
tmp=(LL)tmp * tmp % mo;
if (y % 2==1) tmp=(LL)tmp*x % mo;
return tmp;
}
int C(int n,int m)
{
return (LL)Fact[n] * Ie[m] % mo * Ie[n-m] % mo;
}
int main()
{
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%d",&X[i]);
s[i]=s[i-1]+X[i];
}
n=s[m];
for (int i=1;i<=m;i++) scanf("%d",&Y[i]);
Fact[0]=Ie[0]=1;
for (int i=1;i<=n;i++)
{
Fact[i]=(LL)Fact[i-1]*i % mo;
Ie[i]=quick(Fact[i],mo-2);
}
f[0][0]=1;
for (int i=1;i<=m;i++)
{
for (int j=0;j<=s[i];j++)
{
for (int k=0;k<=min(j,Y[i]);k++)
{
f[i][j]=(f[i][j]+(LL)f[i-1][j-k] * C(s[i]-j+k,k) % mo) % mo;
}
}
}
int ans=f[m][n];
for (int i=1;i<=m;i++) ans=(LL)ans * C(n-s[i-1],X[i]) % mo;
printf("%d\n",ans);
return 0;
}