luogu P4707 重返现世

https://www.luogu.com.cn/problem/P4707

\(kthmin-max\)容斥入门题

懒得证明了
式子就是

\[\max(S)=\sum_{T⊆S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min(T) \]

设计DP
\(f[i][j][k]\)表示考虑前\(i\)个元素\(\sum p=j\) 计算中\(k\)的大小(主要是方便转移下面拆组合数)

然后分选不选转移即可

这篇写得详细一些

https://www.luogu.com.cn/blog/Sooke/solution-p4707

code:


#include<bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
ll qpow(ll x, ll y) {
    ll ret = 1;
    for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
    return ret;
}
int n, K, m, p[1005];
ll f[2][10005][15];
int main() {
    scanf("%d%d%d", &n, &K, &m), K = n - K + 1;
    for(int i = 1; i <= n; i ++) scanf("%d", &p[i]);

    f[0][0][0] = 1;
    for(int i = 1; i <= n; i ++) {
        memset(f[i & 1], 0, sizeof f[i & 1]);
        f[i & 1][0][0] = 1;
        for(int j = 1; j < p[i]; j ++)
            for(int k = 1; k <= K; k ++) f[i & 1][j][k] = f[(i - 1) & 1][j][k];
        for(int j = p[i]; j <= m; j ++)
            for(int k = 1; k <= K; k ++)
                f[i & 1][j][k] = (f[(i - 1) & 1][j][k] + f[(i - 1) & 1][j - p[i]][k - 1] - f[(i - 1) & 1][j - p[i]][k] + mod) % mod;
    }

    ll ans = 0;
    for(int i = 1; i <= m; i ++) (ans += f[n & 1][i][K] * qpow(i, mod - 2) % mod * m % mod) %= mod;
    printf("%lld", ans);
    return 0;
}
posted @ 2021-12-17 09:01  lahlah  阅读(33)  评论(0编辑  收藏  举报