要求的是三部分:
1.只考虑从所有人中选出K个人被碾压的方案数
2.只考虑所有人每门成绩高低关系(高于B神或低于B神)的方案数
3.只考虑所有人的具体成绩方案数
答案显然是三数相乘
(下文中下标均从1开始,比如(文中U_i表示题中U_{i-1}))
第一部分
显然是(C_{N-1}^K)
第二部分
每门都要有(R-1)个人的成绩超过B神
考虑(F(x)=prodlimits_{i=1}^MC_x^{R_i-1})表示每门有R-1个人超过B神的方案数
设d=N-K-1
由容斥得(G=sumlimits_{i=0}^d (-1)^{d-i}C_d^i F(i))表示d个人不被碾压的方案数
第三部分
首先只考虑一门的方案数
a个人分布在b分里的方案数为(b^a)
先考虑B神分数为x时的方案数为(x^{N-R}(U-x)^{R-1})
所以第 i 门的方案数为(H(i)=sumlimits_{x=1}^{U_i} x^{N-R_i} (U_i-x)^{R_i-1})
把((U_i-x)^{R_i-1})二项式定理展开得到(sumlimits_{t=0}^{R_i-1}(-x)^t U_i^{R_i-t-1}C_{R_i-1}^t)
[ herefore H(i)
=sumlimits_{x=1}^{U_i}x^{N-R_i}sumlimits_{t=0}^{R_i-1}(-1)^tx^tU_i^{R_i-t-1}C_{R_i-1}^t\
=sumlimits_{x=1}^{U_i}sumlimits_{t=0}^{R_i-1}(-1)^tx^{N-R_i}x^tU_i^{R_i-t-1}C_{R_i-1}^t\
=sumlimits_{x=1}^{U_i}sumlimits_{t=0}^{R_i-1}(-1)^tx^{N-R_i+t}U_i^{R_i-t-1}C_{R_i-1}^t\
=sumlimits_{t=0}^{R_i-1}sumlimits_{x=1}^{U_i}(-1)^tx^{N-R_i+t}U_i^{R_i-t-1}C_{R_i-1}^t\
=sumlimits_{t=0}^{R_i-1}(-1)^tU_i^{R_i-t-1}C_{R_i-1}^tsumlimits_{x=1}^{U_i}x^{N-R_i+t}\
]
其中(sumlimits_{x=1}^{U_i}x^{N-R_i+t})是连续自然数幂和
根据定理: 前N个自然数的K次幂和一定能表示为关于N的K+1次多项式
就可以用拉格朗日插值在(O(N))的时间内算出
那么M门加一起的方案数是(prodlimits_{i=1}^M H(i)), 时间复杂度(O(N^2M))
结论
(ans=C_{N-1}^K Gprodlimits_{i=1}^MH(i))
代码
#include<bits/stdc++.h>
const int N=305;
const int mod=1e9+7;
int Pow(int x,int f=mod-2){
int re=1;
while(f){
if(f&1)re=1ll*re*x%mod;
f>>=1;
x=1ll*x*x%mod;
}
return re;
}
namespace Lagrange{
int mul[N];
int Lagrange(int n,int t,int *f){
if(t<=n)return f[t];
int re=0,s=1;
for(int i=1;i<=n;i++)s=1ll*s*(t-i)%mod;
for(int i=1;i<=n;i++){
int tmp=1ll*s*f[i]%mod;
int div=1ll*mul[i-1]*mul[n-i]%mod;
div=1ll*div*(t-i)%mod;
div=Pow(div);
tmp=1ll*tmp*div%mod;
if((n-i)&1)re=(re-tmp+mod)%mod;
else re=(re+tmp)%mod;
}
return re;
}
void Pre(int t,int *f){
mul[0]=mul[1]=1;
for(int i=2;i<=t+2;i++)mul[i]=1ll*mul[i-1]*i%mod;
for(int i=1;i<=t+2;i++)f[i]=(f[i-1]+Pow(i,t))%mod;
}
int f[N];
int Sum(int n,int t){
Pre(t,f);
int re=Lagrange(t+2,n,f);
return re;
}
}
int n,m,k,u[N],r[N],c[N][N];
void Init(){
c[0][0]=1;
for(int i=1;i<=n;i++){
c[i][0]=1;
for(int j=1;j<=i;j++){
c[i][j]=c[i-1][j-1]+c[i-1][j];
c[i][j]%=mod;
}
}
}
int Count(int x){
int re=1;
for(int i=1;i<=m;i++)
re=1ll*re*c[x][r[i]-1]%mod;
return re;
}
signed main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)scanf("%d",u+i);
for(int i=1;i<=m;i++)scanf("%d",r+i);
Init();
int ans=0,tmp,d=n-k-1;
for(int i=0;i<=d;i++){
int tmp=((d-i)&1)?mod-1:1;
tmp=1ll*tmp*c[d][i]%mod;
tmp=1ll*tmp*Count(i)%mod;
ans=(ans+tmp)%mod;
}
for(int i=1,s;i<=m;i++){
s=0;
for(int t=0;t<r[i];t++){
tmp=(t&1)?mod-1:1;
tmp=1ll*tmp*Pow(u[i],r[i]-t-1)%mod;
tmp=1ll*tmp*c[r[i]-1][t]%mod;
tmp=1ll*tmp*Lagrange::Sum(u[i],n+t-r[i])%mod;
s=(s+tmp)%mod;
}
ans=1ll*ans*s%mod;
}
ans=1ll*ans*c[n-1][k]%mod;
printf("%d",ans);
return 0;
}