P4707 重返现世 题解

Statement

P4707 重返现世 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

Solution

考虑 min-max 容斥,题目所求即 mink(U)

知道 k 较大但 nk 很小,所以考虑转化一下,知道 mink(U)=maxn+1k(U) ,下面的所有 k 都是 n+1k 的意思,直接套用 min-max 容斥的公式:

E(maxk(U))=TU(1)|T|k(|T|1k1)E(min(T))

由几何分布,知道 E(min(T))=1iTpi ,其中 pi 表示 i 物品出现概率

这样直接做的时间复杂度是 O(2n) 左右的,显然要 G,但是容易发现其实很多的 E(min(T)) 的值域 m 比较小,所以我们的一个重要优化思路 dp 出现了,其主旨是求出对于每一个 min(T) 而言,他前面的系数和。

fi,j,k 表示前 i 个物品,所有集合 T 满足 xTpx=j ,确定式子中 k 值的时候的 (1)|T|k(|T|1k1) 的值

我们的转移类似背包,如若第 i 个物品不选,那么 fi,j,k=fi1,j,k

如若第 i 个物品选了,因为这个时候我们往集合 T 里面塞了一个 i 进去,理应从 fi1,jpi 转过来,同时因为 |T| 增加 1 ,所以 (1)|T|k 变号,又有 (|T|k1)=(|T|1k1)+(|T|1k2)

知道 fi,j,k=fi1,jp,k1fi1,jp,k (注意到 k1 的时候,(1)|T|k 再次变号)

转移即可,时间复杂度 O(nmk) ,空间复杂度滚掉第一维后 O(mk),答案即为 ifn,i,ki

初值 f0,0,0=(1)0(11)=1 即可

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e3+5;
const int M = 1e4+5;
const int mod = 998244353;

int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    return s*w;
}

int p[N],dp[M][15],inv[M];
int n,m,K;

int ksm(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod,b>>=1;
    }
    return res;
}

signed main(){
    n=read(),K=n-read()+1,m=read();
    for(int i=1;i<=n;++i)p[i]=read(); inv[0]=dp[0][0]=1;
    for(int i=1;i<=m;++i)inv[i]=ksm(i,mod-2);
    for(int i=1;i<=n;++i)
        for(int j=m;j>=p[i];--j)
            for(int k=K;k;--k)
                (dp[j][k]+=(dp[j-p[i]][k-1]-dp[j-p[i]][k]+mod)%mod)%=mod;
    int ans=0;
    for(int i=0;i<=m;++i)(ans+=dp[i][K]*inv[i]%mod)%=mod;
    printf("%lld\n",ans*m%mod);
    return 0;
}
posted @   _Famiglistimo  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示