解题思路:
我们设
f[i][j]
表示前
i
门课,共有
假设从
f[i−1][w]转移到f[i][j](j≥w)
没被碾压的人数本应增加
Ri−1
人,但其中有一部分可能之前就没被碾压了。
则有
t1=j−w
个人是新增的人数,要从
n−1−w
个人中选,方案数为
Ct1n−1−w
还有
t2=Ri−1−t1
个人是本就没被碾压的,要从
w
个人中选,方案数为
例如
w=100,Ri−1=5,j=102,则t1=2,t2=3
考虑第
i
门课的得分方案,若B神得了
g(i)=∑x=1Ui(Ui−x)r−1xn−r
由于
Ui
很大,无法直接算,但注意到它是一个关于
Ui
的次数小等于n次的多项式,所以可以用拉格朗日插值法插
U=1,2……n+1
得到
n+1
个点进而算出
g(i)
的值。
由于
Ri
不同,所以对于每门课都要求一遍。
至此得到总的dp方程:
f[i][j]=g(i)∑w=0jCt1n−1−wCt2wf[i−1][w]
时间复杂度为 O(n3)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=105,p=1e9+7;
int n,m,k;
int U[N],R[N],c[N][N],f[N][N];
int g[N],inv[N];
int ksm(int x,int y)
{
x%=p;int res=1;
for(;y;y>>=1,x=1ll*x*x%p)
if(y&1)res=1ll*res*x%p;
return res;
}
int Inter(int u,int r)
{
memset(g,0,sizeof(g));
for(int x=1;x<=n+1;x++)
{
for(int i=1;i<=x;i++)
g[x]=(g[x]+1ll*ksm(x-i,r-1)*ksm(i,n-r)%p)%p;
if(u==x)return g[x];
}
for(int i=1;i<=n+1;i++)
{
inv[i]=1;
for(int j=1;j<=n+1;j++)
if(i!=j)inv[i]=(1ll*inv[i]*(i-j)%p+p)%p;
inv[i]=ksm(inv[i],p-2);
}
int res=0;
for(int i=1;i<=n+1;i++)
{
int tmp=1ll*inv[i]*g[i]%p;
for(int j=1;j<=n+1;j++)
if(i!=j)tmp=1ll*tmp*(u-j)%p;
res=(res+tmp)%p;
}
return res;
}
int C(int i,int j)
{
if(i<0||j<0||j>i)return 0;
return c[i][j];
}
int main()
{
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
n=getint(),m=getint(),k=getint();
for(int i=1;i<=m;i++)U[i]=getint();
for(int i=1;i<=m;i++)R[i]=getint();
c[0][0]=1;
for(int i=1;i<=n;i++)
{
c[i][0]=1;
for(int j=1;j<=n;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%p;
}
f[0][0]=1;
for(int i=1;i<=m;i++)
{
int tmp=Inter(U[i],R[i]);
for(int j=0;j<=n;j++)
{
for(int w=0;w<=j;w++)
f[i][j]=(f[i][j]+1ll*f[i-1][w]*C(n-1-w,j-w)%p*C(w,R[i]-1-(j-w))%p*tmp%p)%p;
}
}
cout<<f[m][n-1-k]<<'\n';
return 0;
}