zoukankan      html  css  js  c++  java
  • 【PKUSC2018】【loj6433】最大前缀和 状压dp

    这题吼啊...

    然而还是想了$2h$,写了$1h$。

    我们发现一个性质:若一个序列$p$能作为前缀和,那么在序列$p$中,包含序列$p$最后一个数的所有子序列必然都是非负的。

    那么,我们

    令$f[i]$表示状态$i$中所有数字全部作为前缀和的方案数。

    令$g[i]$表示状态$i$中所有数字所组合成的任意排列中,前缀和永远为负数的方案数。

    令$s[i]$表示状态$i$中所有数字之和。

    ps:若i的第j个二进制位为$1$,则表示状态$i$中,选择了数字$a_j$。($a$序列的下表为$0$到$n-1$)

     

    通过冷静分析,不难得出:

    $s[i]$很好求

    $f[i]=sum_{(2^j and i)=2^j∩s[i-2^j]+a[j]≥0} f[i-2^j]$

    $g[i]=sum_{(2^j and i)=2^j∩s[i-2^j]+a[j]<0} g[i-2^j]$

    显然$f[0]=g[0]=1$。

    统计答案时,分前缀和$≥0$,前缀和$<0$两类讨论。

    当前缀和$≥0$时

    $ans1=sum_{i=1}^{2^n-1} s[i] imes f[i] imes g[2^n-1-i] $

    当前缀和<0时

    $ans2=sum_{j=0}^{n=1} sum_{i=0} (a[j]+s[i]) imes f[i] imes g[2^n-1-i-2^j] [(2^j and i=0)∩s[i]<0∩s[i]>-a[j]]$

    最终所求答案即$ans1+ans2$。

    然后就完结了。

    时间复杂度为$O(n imes 2^n)$。

     1 #include<bits/stdc++.h>
     2 #define M 20
     3 #define L long long
     4 #define MOD 998244353
     5 using namespace std;
     6 
     7 L f[1<<M]={0},g[1<<M]={0},a[M]={0},he[1<<M]={0};
     8 
     9 int main(){
    10     int n,m; scanf("%d",&n); m=1<<n;
    11     for(int i=0;i<n;i++) cin>>a[i];
    12     for(int i=0;i<m;i++)
    13     for(int j=0;j<n;j++) 
    14     if(i&(1<<j)) he[i]+=a[j];
    15     f[0]=1; 
    16     for(int i=1;i<m;i++){
    17         for(int j=0;j<n;j++)
    18         if((i&(1<<j))&&he[i^(1<<j)]+a[j]>=0){
    19             f[i]=(f[i]+f[i^(1<<j)])%MOD;
    20         }
    21     }
    22     for(int i=0;i<n;i++) a[i]=-a[i];
    23     for(int i=0;i<m;i++) he[i]=-he[i];
    24     g[0]=1;
    25     for(int i=1;i<m;i++){
    26         for(int j=0;j<n;j++)
    27         if((i&(1<<j))&&he[i^(1<<j)]+a[j]>0){
    28             g[i]=(g[i]+g[i^(1<<j)])%MOD;
    29         }
    30     }
    31     for(int i=0;i<n;i++) a[i]=-a[i];
    32     for(int i=0;i<m;i++) he[i]=-he[i];
    33     L ans=0;
    34     for(int j=0;j<n;j++) if(a[j]<0){
    35         //f[1<<j]=1;
    36         for(int i=0;i<m;i++)
    37         if((i&(1<<j))==0){
    38             if(he[i]<0||he[i]>-a[j]) continue;
    39             int hh=(m-1)^i^(1<<j);
    40             ans=(ans+(a[j]+he[i])*f[i]%MOD*g[hh]%MOD+MOD)%MOD;
    41         }
    42     }
    43     for(int i=0;i<m;i++)
    44     ans=(ans+f[i]*he[i]%MOD*g[(m-1)^i]%MOD+MOD)%MOD;
    45     cout<<ans<<endl;
    46 }
    47     
  • 相关阅读:
    linux advancing program signal [copy]
    advacing lnux program zombie process [copy]
    Devpress.XtraGrid.GridControl 笔记(转载)
    嵌入别的程序到winform(C#)
    GridControl控件使用小结
    .net 时间类型的一小bug ToShortDateString()
    gridControl repositoryItemLookUpEdit控件使用
    .net架构的最后思考(箴言)
    VS项目引用,无法更新
    关于ZendOptimizer和wamp的phpmyadmin冲突问题
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9170243.html
Copyright © 2011-2022 走看看