题解 P3270【[JLOI2016]成绩比较】
题意
有 名学生, 名课程,一位同学在第 门课程中可被评为 范围内的分数。其中有一位同学,在第 门课程中排名 ,其余 名同学中有 名每门的分数都不高于这位同学。
求方案数,对 取模。
思路
首先我们将问题用乘法原理划分:
- 从 个同学中选出 个同学被 B 神碾压的方案数;
- 剩余 个同学在课程中与 B 神成绩的大小关系的方案数;
- 每科中每名同学具体成绩方案数。
第一部分
答案显然为 。
第二部分
我们仍可以使用乘法原理将问题分解为单科的子问题,第 科中,比 B 神高的只有 名,则方案数为 。
但是我们求出的只是有不超过 人被碾压,因为我们需要保证 个人都被选中了至少一次,我们设 即不超过 人被碾压时的方案数,容斥后得到答案为
第三部分
拆分为单科后设 表示分数上限为 ,有 人比 B 神高, 人不比 B 神高的方案数,显然:
直接暴力求则会得到一个 的暴力(),无法通过。
接下来可以通过二项式定理展开+拉格朗日插值求自然数 次幂和的方法解决,不过我们这里使用神仙 的做法:枚举 人有 种得分的方案数,设为 ,算出每类的方案数之和即可。
可以得出, 人有不超过 种得分的方案数为 为了得出 ,我们考虑容斥,易得 设 ,这部分的答案即为
则最终答案为三部分乘在一起。
预处理组合数和 (),则三部分复杂度分别为 ,总时间复杂度为 ,且此方法码量较少。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=100+10,mod=1e9+7;
int n,m,k,u[N],r[N];
int C[N][N],pw[N][N],inv[N];
inline int qpow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
inline void Prefix(int n){
inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=0;i<=n;i++){
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
for(int i=0;i<=n;i++){
pw[i][0]=1;
for(int j=1;j<=n;j++)
pw[i][j]=1ll*pw[i][j-1]*i%mod;
}
}
inline int Type1(){
return C[n-1][k];
}
inline int F(int n){
int ans=1;
for(int i=1;i<=m;i++)
ans=1ll*ans*C[n][r[i]-1]%mod;
return ans;
}
inline int Type2(){
int t=n-k-1;
int ans=0;
for(int i=0;i<t;i++){
int tmp=1ll*F(t-i)*C[t][i]%mod;
ans=(ans+(i&1?mod-tmp:tmp))%mod;
}
return ans;
}
int D[N];
inline int G(int n,int a,int b){
int ans=0;
for(int i=0;i<n;i++)
ans=(ans+1ll*pw[i][a]*pw[n-i][b])%mod;
return ans;
}
inline int Gpi(int u,int a,int b){
int ans=0,tmp=1;
for(int i=1;i<=n;i++){
D[i]=G(i,a,b);
for(int j=1;j<i;j++)
D[i]=(D[i]+mod-1ll*D[j]*C[i][j]%mod)%mod;
tmp=1ll*tmp*(u-i+1)%mod*inv[i]%mod;
ans=(ans+1ll*tmp*D[i])%mod;
}
return ans;
}
inline int Type3(){
int ans=1;
for(int i=1;i<=m;i++)
ans=1ll*ans*Gpi(u[i],r[i]-1,n-r[i])%mod;
return ans;
}
int main(){
Prefix(N-10);
n=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();
write(1ll*Type1()*Type2()%mod*Type3()%mod);
flush();
}
再见 qwq~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】