zoukankan      html  css  js  c++  java
  • [PKUSC2018]最大前缀和(状压DP)

    题目大意:求给定的 $n$ 个数的所有排列的最大前缀和(不能为空)之和对 $10^9+7$ 取模的值。

    $1le nle 20,1lesum|a_i|le 10^9$。


    神级DP。杂题选讲的神级毒瘤讲题人CDW讲的。

    考虑一个集合 $S$ 能作为最大前缀和出现的方案数。(即贡献系数)

    发现前 $|S|$ 个数满足最大前缀和是整个序列,后 $n-|S|$ 个数满足最大前缀和 $<0$。(虽然 $le 0$ 也行,但为了避免重复统计就要 $<0$)

    设 $f[S]$ 为在 $S$ 的所有排列中,最大前缀和 $<0$ 的个数。

    设 $g[S]$ 为在 $S$ 的所有排列中,最大前缀和 $=sum[S]$ 的个数。($sum$ 是和)

    $f[S]=egin{cases}0&sum[S]ge 0\ sumlimits_{iin S}f[S-{i}]&sum[S]<0end{cases}$

    初始 $f[0]=1$。

    解释一下,如果 $sum[S]ge 0$,那么最大前缀和不会小于 $0$。否则枚举最后一个数,当且仅当前面的最大前缀和 $<0$ (或者前面没有数,所以 $f[0]=1$)且 $sum[S]<0$ 时才可以。第二个条件已经保证满足了。

    $g[S] ightarrow g[S+(1<<i)](sum[S]ge 0,i otin S)$

    初始 $g[{i}]=1$。

    解释一下,考虑从已有状态扩展,枚举在 $S$ 前加一个数 $i$,当且仅当 $S$ 最大前缀和是自己时,新序列最大前缀和才是自己。、

    答案为 $sum sum[S]g[S]f[U-S]$。

    时间复杂度 $O(n2^n)$。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline int read(){
        char ch=getchar();int x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,a[22],ans,f[1111111],g[1111111];
    ll S[1111111];
    int main(){
        n=read();
        FOR(i,0,n-1) a[i]=read(),g[1<<i]=1;
        FOR(i,0,(1<<n)-1) FOR(j,0,n-1) if((i>>j)&1) S[i]+=a[j];
        f[0]=1;
        FOR(i,0,(1<<n)-1){
            if(S[i]>=0){FOR(j,0,n-1) if(!((i>>j)&1)) g[i|(1<<j)]=(g[i|(1<<j)]+g[i])%mod;}
            else FOR(j,0,n-1) if((i>>j)&1) f[i]=(f[i]+f[i^(1<<j)])%mod;
        }
        FOR(i,0,(1<<n)-1) ans=(ans+1ll*(S[i]+mod)%mod*g[i]%mod*f[((1<<n)-1)^i])%mod;
        printf("%d
    ",ans);
    }
    View Code
  • 相关阅读:
    java 或者 js 获取项目访问路径(域名)
    jquery validate 使用示例
    项目中调试SQLServer 方便的查看SQL语句的执行时间的方法
    Oracle Replace函数的简单使用
    LINE_NO in format of XXXX example -> Line 10 is 0010
    Oracle序列使用:建立、删除、使用
    Oracle 存储过程创建及调用
    char、varchar、varchar2区别
    missing equal sign
    [转]Windows中的句柄(handle)
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10922069.html
Copyright © 2011-2022 走看看