重返現世 解題報告

重返現世

kthmin-max容斥板子題git

題目要求至少獲得\(k\)種東西的指望時間,轉換後是求獲得全集倒數第\(k\)個得到的東西的指望時間,而後能夠套式子了數組

\[\begin{aligned} \max_k(S)&=\sum_{\varnothing\not=T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min(T)\\ &=\sum_{\varnothing\not=T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\frac{m}{\sum \limits_{i\in T}p_i} \end{aligned} \]

而後咱們這個答案式子作dpspa

\(dp_{i,j,k}\)表明前\(i\)個東西處理後\(\sum p=j\)且爲求\(kmax\)的貢獻值code

這裏說一下第三個狀態,這個\(k\)其實就是式子裏面的\(k\),咱們設它只是爲了轉移這個組合式子而已(利用組合數的遞推式子)get

轉移有it

\[dp_{i,j,k}=dp_{i-1,j,k}-dp_{i-1,j-p_i,k}+dp_{i-1,j-p_i,k-1} \]

初始狀態io

\[dp_{i,0,0}=1 \]

目標class

\[\sum_{i=1}^m\frac{m}{i}dp_{n,i,k} \]

而後滾動一下數組就行了im


Code:di

#include <cstdio>
#include <cctype>
template <class T>
void read(T &x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
const int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
#define mul(a,b) (1ll*(a)*(b)%mod)
int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
int n,m,K,dp[2][10010][11],p[10010],cur;
int main()
{
	read(n),read(K),read(m);
	K=n-K+1;
	for(int i=1;i<=n;i++) read(p[i]);
	dp[0][0][0]=1;
	for(int i=1;i<=n;i++)
	{
		cur^=1;
		for(int j=0;j<=m;j++)
			for(int k=0;k<=K;k++)
			{
				dp[cur][j][k]=dp[cur^1][j][k];
				if(j>=p[i]&&k)
                {
                    dp[cur][j][k]=add(dp[cur][j][k],mod-dp[cur^1][j-p[i]][k]);
                    dp[cur][j][k]=add(dp[cur][j][k],dp[cur^1][j-p[i]][k-1]);
                }
			}
	}
	int ans=0;
	for(int i=1;i<=m;i++) ans=add(ans,mul(m,mul(qp(i,mod-2),dp[cur][i][K])));
	printf("%d\n",ans);
	return 0;
}

2019.3.2

相關文章
相關標籤/搜索