解析
依然不会亚qwq
但这次至少有点上道了
(指推出了一个会导致重复计数的错误式子)
首先,我们要选出碾压那些人,方案数就是Cn−1kC_{n-1}^kCn−1k
然后,我们要统计每门学科的排名情况
考虑比B神分数高的人一定是从没被碾压的人里选。所以对应的方案就是Cn−k−1ri−1C_{n-k-1}^{r_i-1}Cn−k−1ri−1,设为fkf_kfk
但是这样随便选可能会导致有的应该没被碾压的人一直没被选到,被碾压,所以这个东西其实是至少碾压kkk人的方案数
那么使用常规的容斥套路,这部分的答案就是fk−fk+1+fk+2−...f_k-f_{k+1}+f_{k+2}-...fk−fk+1+fk+2−...
最后,我们要统计每门学科的分数情况
设gu,a,bg_{u,a,b}gu,a,b表示总分数为u,B神前面有a个人,后面有b个人的方案数
枚举B神的分数 i,那么就有:
gu,a,b=∑i−1u(u−i)a∗ibg_{u,a,b}=\sum_{i-1}^u(u-i)^a*i^bgu,a,b=i−1∑u(u−i)a∗ib
但是这个东西暴力算是On的
(PS:我就是卡在这里了)qwq
考虑由于a和b非常少,我们可以使用离散化的思路
设n个人的分数一共有t个取值
枚举t,就有:
gu,a,b=∑t=1ngt,a,b×Cutg_{u,a,b}=\sum_{t=1}^ng_{t,a,b}\times C_u^tgu,a,b=t=1∑ngt,a,b×Cut
里面的 g 可以暴力求解
问题得以解决
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
#define ll long long
#define il inline
il ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
int n,m,k;
ll c[105][105],u[105],r[105],mx=1000;
ll sum[105],jc[105],ni[105];
inline ll ksm(ll x,ll k){ll res=1;while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res;
}
ll f[105][105];ll D[105];
inline ll g(ll u,ll a,ll b){ll res(0);for(int i=1;i<=u;i++){res+=f[u-i][a]*f[i][b];res%=mod;}return res;
}
ll G(ll u,ll a,ll b){ll C=1,ans=0;//printf("\nG:u=%lld a=%lld b=%lld\n",u,a,b);for(int t=1;t<=n;t++){ll now=g(t,a,b);for(int i=1;i<t;i++) now=(now-D[i]*c[t][i]%mod+mod)%mod;D[t]=now;C=C*(u-t+1)%mod*jc[t-1]%mod*ni[t]%mod;ans+=now*C;ans%=mod;//printf(" t=%d C=%lld now=%lld ans=%lld\n",t,C,D[t],ans);}return ans;
}int main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifn=read();m=read();k=read();for(int i=1;i<=m;i++) u[i]=read();for(int i=1;i<=m;i++) r[i]=read(),mx=min(mx,n-r[i]);jc[0]=1;for(int i=1;i<=100;i++) jc[i]=jc[i-1]*i%mod;ni[n]=ksm(jc[n],mod-2);for(int i=n-1;i>=0;i--) ni[i]=ni[i+1]*(i+1)%mod;for(int i=0;i<=100;i++){f[i][0]=1;for(int j=1;j<=100;j++) f[i][j]=f[i][j-1]*i%mod;}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])%mod;}}for(int i=1;i<=m;i++){sum[i]=G(u[i],r[i]-1,n-r[i]);//printf("i=%d sum=%lld\n",i,sum[i]);}ll ans=0;for(int o=k;o<=n;o++){ll now=c[n-k-1][n-o-1];//printf(" i=0 now=%lld\n",now);for(int i=1;i<=m;i++){//now=now*c[n-o-1][r[i]-1]%mod;now=now*c[n-o-1][r[i]-1]%mod*sum[i]%mod;//printf(" i=%d now=%lld\n",i,now);}if((o-k)&1){ans-=now;if(ans<0) ans+=mod;}else{ans+=now;if(ans>=mod) ans-=mod;}//printf("o=%d now=%lld ans=%lld\n\n",o,now,ans);//printf("o=%d now=%lld\n",o,now);}//for(int i=1;i<=m;i++){//ans=ans*sum[i]%mod;//printf("i=%d ans=%lld\n",i,ans);//}printf("%lld\n",ans*c[n-1][k]%mod);return 0;
}
/**/