首页 > 其他分享 >【容斥、插值】P3270 [JLOI2016]成绩比较

【容斥、插值】P3270 [JLOI2016]成绩比较

时间:2023-02-22 22:35:10浏览次数:34  
标签:分数 JLOI2016 return P3270 int ll 容斥 MAXN MOD

【容斥、插值】P3270 [JLOI2016]成绩比较

题目简述

  • 有 \(n+1\) 个人,进行 \(m\) 场考试,第 \(i\) 场考试的可能得分是 \([0,U_i]\) 之间的整数。
  • 假设你是其中一人,你知道每场考试的排名 \(r_i\)(相同分数算后排名),并且恰有 \(k\) 个人每一场考试的分数都不大于你。
  • 求方案数,对 \(10^9+7\) 取模。
  • \(n,m\leq 100\),\(U_i\leq10^9\)。

解题思路

很显然的计数分为三个部分:

  • 确定被你碾压的 \(k\) 人。
  • 确定每个人和你分数的大小关系。
  • 确定每个人的分数。

对于第 \(1\) 部分,显然是 \(C_n^k\)。

对于第 \(2\) 部分,我们可以通过排名确定出每场比赛 \(i\) 有多少人分数 $\leq $ 你,多少人分数 \(>\) 你。那么由于已经确定出 \(k\) 个被碾压的人了,所以这 \(k\) 个人的分数 $\leq $ 你,我们的问题转换成在剩下的人当中去分配 \(R_i\) 使得每个人至少有一个 \(>\) 你的分数。很显然的可以使用容斥。

由于 \(k\) 个被碾压者已经确定,记剩下的人 \(N=n-k\),假设有:

\[f_i=\prod_{j=1}^m C^{r_j-1}_{i} \]

表示有至多 \(i\) 个人被你碾压,很显然的容斥为:

\[ans=\sum_{i=0}^N (-1)^{N-i}\times f_i\times C_{N}^i \]

对于第三部分,每一场考试是独立的,我们可以写出式子:

\[\sum_{k=0}^{U_i} k^{n-r_i+1}\times (U_i-k)^{r_i-1} \]

我们不难发现原式改写成 \(\sum_{k=0}^{x} k^{n-r_i+1}\times (U_i-k)^{r_i-1}\) 是关于 \(x\) 的 \(n+1\) 次多项式,所以我们对于 \(\leq n+2\) 的值暴力枚举,然后使用插值求出 \(x=U_i\) 的值即可。

暴力拉格朗日的复杂度 \(O(n^2\log V)\),可以通过。我们也可以优化到 \(O(n\log n)\) 的拉格朗日。

参考代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MP make_pair
const int MAXN=105;
const int MOD=1e9+7;
int n,m,k;
int x[MAXN],r[MAXN];
ll fac[MAXN],inf[MAXN];
ll ksm(ll a,int b){ll res=1;while(b){if(b&1)res=res*a%MOD;a=a*a%MOD,b>>=1;}return res;}
ll inv(ll a){return ksm(a,MOD-2);}
void init(){
	fac[0]=inf[0]=1;
	for(int i=1;i<MAXN;i++)
		fac[i]=fac[i-1]*i%MOD,
		inf[i]=inv(fac[i]);
	return;
}
ll C(int n,int m){if(n>m) return 0;return fac[m]*inf[n]%MOD*inf[m-n]%MOD;}
ll sgn(int x){return (x&1)?-1:1;}
ll Part_2(){
	ll f[MAXN];
	for(int i=0;i<=n;i++){
		f[i]=1;
		for(int j=1;j<=m;j++)
			f[i]=f[i]*C(r[j]-1,i)%MOD;
	}
	ll res=0;
	int d=n-k;
	for(int i=0;i<=d;i++)
		res=(res+sgn(d-i)*f[i]%MOD*C(i,d)%MOD+MOD)%MOD;
	return res;
}
ll Func(ll x,int a,int b){
	ll y[MAXN],res=0;
	for(int i=1;i<=n+2;i++){
		res+=ksm(i,a)*ksm(x-i+MOD,b)%MOD;
		res%=MOD;
		y[i]=res;
	}
	ll ans=0;
	for(int i=1;i<=n+2;i++){
		res=y[i];
		for(int j=1;j<=n+2;j++)
			if(i!=j)
				res=res*(x-j+MOD)%MOD*inv(i-j+MOD)%MOD;
		ans+=res;ans%=MOD;
	}
	return ans;
}
int main(){
	ios::sync_with_stdio(false);
	init();
	cin>>n>>m>>k;n--;
	for(int i=1;i<=m;i++)
		cin>>x[i];
	for(int i=1;i<=m;i++)
		cin>>r[i];
	ll ans=C(k,n)*Part_2()%MOD;
	for(int i=1;i<=m;i++)
		ans=ans*Func(x[i],n-r[i]+1,r[i]-1)%MOD;
	cout<<ans;
	return 0;
}

标签:分数,JLOI2016,return,P3270,int,ll,容斥,MAXN,MOD
From: https://www.cnblogs.com/KawaiiOU/p/17146246.html

相关文章