zoukankan      html  css  js  c++  java
  • [luogu P4707] 重返现世

    Description

    洛谷题目链接:https://www.luogu.org/problemnew/show/P4707

    Solution

    前置广义(min-max)容斥,不懂的可以看看我的min-max容斥学习笔记

    那么(min{S})显然是比较好求的,具体的:

    [min{S}=frac{m}{sum_{iin S}p_i} ]

    但是注意到(n)的范围很大,显然不能用常规做法。

    注意到(k)很小,可以考虑(dp)

    (f_{x,s,k})表示当前(dp)到前(x)个了,选出来的要满足(sum p=s),且为第(k)大的系数,因为可以注意到后面的(min)都是一样的,我们这里在(dp)当前的(min)被算了多少次,那么这个(dp)状态的意义就是前面那一坨系数,即:

    [sum_{T}(-1)^{|T|-k}inom{|T|-1}{k-1} ]

    并且满足了一堆的条件。

    考虑怎么转移这个(dp),这里显然是要分情况讨论:

    如果不选(x),那么转移就很简单了,直接是(f_{x,s,k}=f_{x-1,s,k})

    否则就有点复杂了,我们先把式子写出来:

    [f_{x,s,k}=sum_{T}(-1)^{|T|-k}inom{|T|-1}{k-1}\ ]

    然后这里的(sum p=s),由于这里硬点(x)要选,我们不妨考虑剩下的部分是啥样的:

    [f_{x,s,k}=sum_{T}(-1)^{|T|+1-k}inom{|T|}{k-1} ]

    注意这里枚举的(T)是不含(x)的,且(sum p=s-p_x),我们尝试着利用组合数的性质把它展开:

    [egin{align} f_{x,s,k}&=sum_{T}(-1)^{|T|+1-k}(inom{|T|-1}{k-1}+inom{|T|-1}{k-2})\ &=-sum_T(-1)^{|T|-k}inom{|T|-1}{k-1}+sum_T(-1)^{|T|-(k-1)}inom{|T|-1}{(k-1)-1}\ &=-f_{x-1,s-p_x,k}+f_{x-1,s-p_x,k-1} end{align} ]

    那么我们就可以得到总的转移方程:

    [f_{x,s,k}=f_{x-1,s,k}-f_{x-1,s-p_x,k}+f_{x-1,s-p_x,k-1} ]

    边界条件就直接(f_{x,0,0}=1)就好了。

    注意这里空间复杂度会爆掉,要把(dp)的第一维滚掉就好了。

    代码真的很好写...

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e5+10;
    const int mod = 998244353;
    
    int qpow(int a,int x) {
    	int res=1;
    	for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
    	return res;
    }
    
    int n,K,m,p[maxn],f[2][10050][12];
    
    int main() {
    	read(n),read(K),read(m);K=n-K+1;
    	for(int i=1;i<=n;i++) read(p[i]);
    	f[0][0][0]=1;
    	for(int t=1;t<=n;t++) {
    		int i=t&1;
    		for(int j=0;j<p[t];j++)
    			for(int k=0;k<=K;k++)
    				f[i][j][k]=f[i^1][j][k];
    		f[i][0][0]=1;
    		for(int j=p[t];j<=m;j++)
    			for(int k=1;k<=K;k++)
    				f[i][j][k]=((f[i^1][j][k]+f[i^1][j-p[t]][k-1])%mod-f[i^1][j-p[t]][k])%mod;
    	}
    	int ans=0;
    	for(int i=1;i<=m;i++) ans=(ans+1ll*f[n&1][i][K]*m%mod*qpow(i,mod-2)%mod)%mod;
    	write((ans+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    Qt5."Clang Code Model"一些设置
    基于element表格的合并多个行实例
    vue中,基于echarts 地图实现一个人才回流的大数据展示效果
    vue2.0 子组件props接受父组件传递的值,能不能修改的问题整理
    vue调用组件,组件回调给data中的数组赋值,报错Invalid prop type check failed for prop value. Expecte
    vue,基于element的tree组件封装
    vue父子组件相互传值的实例
    基于vant实现一个问卷调查
    css3实现倾斜转动的转盘
    0801 am使用tp框架对数据库增删改查
  • 原文地址:https://www.cnblogs.com/hbyer/p/10521485.html
Copyright © 2011-2022 走看看