zoukankan      html  css  js  c++  java
  • 洛谷 P4707 【重返现世】

    题目分析

    题目就是求第K种原料的出现期望时间。

    考虑广义min-max容斥。

    ( ext{kthmax}(S)=sumlimits_{Tsubseteq S}(-1)^{|T|-k}inom{|T|-1}{k-1}min(T))

    显然(min(T)=frac{m}{sumlimits_{iin S}p_i})

    发现(m)的范围很小,那么我们可以考虑设状态dp算贡献。

    (f_{j,k})表示对于集合(|S|)(j=sumlimits_{iin S}p_i),集合大小为(k)的方案数。

    转移显然。

    但是时间复杂度为(O(n^2m)),难以ac。

    观察到还有(|n-k|<=10)的条件,考虑改变状态。

    (f_{j,k})表示对于集合(S)(j=sumlimits_{iin S}p_i)

    组合数下标为(k)(sumlimits_{T}(-1)^{|T|-k}inom{|T|-1}{k-1}min(T))的值。

    对于一个概率为(v)的新物品:

    如果不加入,直接累加前面的答案。

    如果加入,那么答案应该是从(f_{j-v,k-1})转移过来。

    我们观察一波式子(标解)

    我们用(g_{i,j})表示对于集合(S)(|S|=i)(j= sumlimits_{kin S}p_k)的方案数。

    对于(f_{j-v,k})

    (f_{j-v,k-1}=sumlimits_{i}(-1)^{i-k+1}inom{i-1}{k-2}g_{i,j-v})

    (=-sumlimits_{i}(-1)^{i-k}inom{i-1}{k-2}g_{i,j-v})

    增加一个物品后:

    ( riangle f_{j,k}=sumlimits_i(-1)^{i-k+1}inom{i}{k-1}g_{i,j-v})

    (=-sumlimits_i(-1)^{i-k}inom{i}{k-1}g_{i,j-v})

    两式相减:

    ( riangle f_{j,k}-f_{j-v,k-1}=-sumlimits_i(-1)^{i-k}inom{i-1}{k-1}g_{i,j-v})

    (=-f_{j-v,k})

    因此我们得到了递推式:

    (f_{j,k}=f'_{j,k}+f'_{j-v,k-1}-f'_{j-v,k})

    因此我们就可以(O(m*(n-k)))解决dp。

    答案就是(sumlimits_{i=1}^{m}frac{m}{i}f_{i,k})

    #include <bits/stdc++.h>
    using namespace std;
    inline int Getint(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch))ch!='-'?:f=-1,ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    typedef long long ll;
    const int mod=998244353;
    int n,K,m,f[2][10005][15],p[1005];
    int inv[10005];
    ll Pow(ll x,ll k){
        ll ret=1;
        while(k){
            if(k&1)ret=ret*x%mod;
            k>>=1;x=x*x%mod;
        }
        return ret;
    }
    int main(){
        n=Getint();K=n-Getint()+1;m=Getint();
        for(int i=0;i<=m;i++)inv[i]=Pow(i,mod-2);
        for(int i=1;i<=n;i++)p[i]=Getint();
        int cur=0,pre=1;
        for(int i=1;i<=10;i++)f[cur][0][i]=-1;
        for(int i=1;i<=n;i++){
            cur^=1;pre^=1;
            for(int j=0;j<=m;j++)
                for(int k=1;k<=10;k++){
                    f[cur][j][k]=f[pre][j][k];
                    if(j>=p[i]){
                        f[cur][j][k]=(f[cur][j][k]-f[pre][j-p[i]][k])%mod;
                        if(k>0)f[cur][j][k]=(f[cur][j][k]+f[pre][j-p[i]][k-1])%mod;
                    }
                }
        }
        ll ans=0;
        for(int i=1;i<=m;i++)ans=(ans+1ll*f[cur][i][K]%mod*m%mod*inv[i])%mod;
        cout<<(ans+mod)%mod<<"
    ";
    }
    
  • 相关阅读:
    js实现复制功能 javascript
    《架构整洁之道》之组件聚合
    《架构整洁之道》之组件
    js实现导出word
    js实现导出pdf
    《架构整洁之道》之依赖反转原则
    《架构整洁之道》之接口隔离原则
    《架构整洁之道》之里氏替换原则
    解决js地址栏中传递中文乱码的问题
    Windows安装nginx服务
  • 原文地址:https://www.cnblogs.com/Trrui/p/9994668.html
Copyright © 2011-2022 走看看