洛谷P4707 重返现世 kMAX-MIN反演+DP

博客围绕题目展开分析,先介绍kMAX - MIN反演,推导其反演系数函数f(x)。接着阐述DP方法,将k转化为第n - k + 1小值,设f(j,k)表示相关集合容斥系数和,考虑物品选择情况得出状态转移方程,还提及边界条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目分析

kMAX-MIN反演

设kMAX-MIN反演有反演系数函数f(∣S∣)f(|S|)f(S),使得

kMAX(S)=∑T≠∅,T⊂Sf(∣T∣)MIN(T)kMAX(S)=\sum_{T =\not \emptyset,T \subset S} f(|T|)MIN(T)kMAX(S)=T≠,TSf(T)MIN(T)

假设SSS集合里有nnn个数,分别是a1,a2...ana_1,a_2...a_na1,a2...an,且a1≤a2≤...≤ana_1 \leq a_2 \leq ... \leq a_na1a2...an,那么第kkk大值为an−k+1a_{n-k+1}ank+1

MIN(T)=aiMIN(T)=a_iMIN(T)=aiTTT,满足TTT中最小元素为aia_iai,所以有:

∑i=0n−xCn−xif(i+1)=[x=n−k+1]\sum_{i=0}^{n-x} C_{n-x}^i f(i+1)=[x=n-k+1]i=0nxCnxif(i+1)=[x=nk+1]

上二项式反演得到:

f(x+1)=∑i=0x(−1)x−iCxi[i=k−1]=(−1)x−k+1Cxk−1f(x+1)=\sum_{i=0}^{x} (-1)^{x-i}C_x^i[i=k-1]=(-1)^{x-k+1}C_x^{k-1}f(x+1)=i=0x(1)xiCxi[i=k1]=(1)xk+1Cxk1

综上,f(x)=(−1)x−kCx−1k−1f(x)=(-1)^{x-k}C_{x-1}^{k-1}f(x)=(1)xkCx1k1

答案就是

∑T≠∅(−1)∣T∣−KC∣T∣−1K−1m∑i∈Tpi\sum_{T =\not \emptyset}(-1)^{|T|-K}C_{|T|-1}^{K-1}\frac{m}{\sum_{i \in T}p_i}T≠(1)TKCT1K1iTpim

DP

不难发现本题的kkk应该转化为第n−k+1n-k+1nk+1小值,而n−k≤10n-k \leq 10nk10,所以n−k+1≤11n-k+1 \leq 11nk+111。再加上nnnmmm都不大,大胆猜想应该把它们都算进复杂度中。

f(j,k)f(j,k)f(j,k)表示,对于当前考虑到的∑i∈Tpi=j\sum_{i \in T}p_i=jiTpi=j的集合,当K=kK=kK=k时,它们的容斥系数(反演系数)的和。

一个个考虑每种物品,如果不选择第iii种物品:f(j,k)+=f′(j,k)f(j,k)+=f'(j,k)f(j,k)+=f(j,k)

如果选择,首先是−1-11的次方改变,这个很好办。然后组合数的问题,C∣T∣−1K−1=C∣T∣−2K−1+C∣T∣−2K−2C_{|T|-1}^{K-1}=C_{|T|-2}^{K-1}+C_{|T|-2}^{K-2}CT1K1=CT2K1+CT2K2,所以综上,f(j,k)+=−f(j−pi,k)+f(j−pi,k−1)f(j,k)+=-f(j-p_i,k)+f(j-p_i,k-1)f(j,k)+=f(jpi,k)+f(jpi,k1)

至于边界,是一个被构造了的,很妙的f(0,0)=0,f(0,k)=−1f(0,0)=0,f(0,k)=-1f(0,0)=0,f(0,k)=1的边界。不过也可以预处理一维的边界啥的。

代码

#include<bits/stdc++.h>
using namespace std;
#define RI register int
const int mod=998244353;
int n,K,m,ans;
int p[1005],inv[10005],f[2][10005][13];

int qm(int x) {return x>=mod?x-mod:x;}
int main()
{
	scanf("%d%d%d",&n,&K,&m);
	K=n-K+1;
	for(RI i=1;i<=n;++i) scanf("%d",&p[i]);
	inv[1]=1;for(RI i=2;i<=m;++i) inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
	for(RI i=1;i<=K;++i) f[0][0][i]=mod-1;
	for(RI i=1,t=1,lim=0;i<=n;++i,t^=1) {
		for(RI j=0;j<=lim;++j)
			for(RI k=1;k<=K;++k) {
				if(!f[t^1][j][k]) continue;
				f[t][j][k]=qm(f[t][j][k]+f[t^1][j][k]);
				f[t][j+p[i]][k+1]=qm(f[t][j+p[i]][k+1]+f[t^1][j][k]);
				f[t][j+p[i]][k]=qm(f[t][j+p[i]][k]-f[t^1][j][k]+mod);
				f[t^1][j][k]=0;
			}
		lim+=p[i];
	}
	for(RI i=1;i<=m;++i) ans=qm(ans+1LL*inv[i]*f[n&1][i][K]%mod);
	ans=1LL*ans*m%mod;
	printf("%d\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值