zoukankan      html  css  js  c++  java
  • 洛谷p5369[PKUSC2018]最大前缀和

    【洛谷P5369】【PKUSC2018】最大前缀和

    题面

    洛谷

    题解

    状压(dp)
    我们设(s[S])表示选了(S)这个状态的数的和,(f[S])表示最大前缀和为(s[S])的方案数,(g[S])表示任意前缀和均为负的方案数。
    我们在输入的时候可以在(O(2^n*n))的复杂度将(s)的值算出来。
    接下来就可以转移了。
    枚举所有状态。
    如果(>0)则若不包含(f[S | (1 << i - 1)] += f[S])
    如果(<0)小于零若包含则(g[S] += g[S ⊕ (1<<i-1)])
    这里的复杂度也是(O(2^n*n))
    答案就是(sum s[S] * f[S] * g[ar{S}])

    代码

    #include <bits/stdc++.h>
    
    const int maxn = 25;
    const int mod = 998244353;  
    typedef long long ll;
    
    int n, m, i, j, k;
    int ans, full;
    int a[maxn], f[1 << maxn], g[1 << maxn];   
    ll s[1 << maxn];
    
    int main() {
    	scanf("%d",&n);
    	full = (1 << n) - 1;
    	g[0] = 1;
    	for(int i = 1;i <= n;i++) {
    		scanf("%d",a + i);    
    		f[1 << i - 1] = 1;
    		for(int S = 0;S <= full;S++)
    			if(S & (1 << i - 1))
    				s[S] += a[i];   
    	}
    	for(int S = 1;S <= full;S++) {
    		if(s[S] > 0) {
    			for(int i = 1, j;i <= n;i++) {
    				if(!(S & (1 << i - 1)))
    					(f[S | (1 << i - 1)] += f[S]) %= mod;     
    			}
    		} else {
    			for(int i = 1, j;i <= n;i++)
    				if(S & (1 << i - 1))
    					(g[S] += g[S ^ (1 << i - 1)]) %= mod;  
    		}
    	}
    	for(int S = 1;S <= full;S++)
            (ans += (ll)s[S] * f[S] % mod * g[S ^ full] % mod) %= mod;
    	printf("%d
    ",(ans + mod) % mod);
    	return 0;    
    }
    
  • 相关阅读:
    某些电脑前面板没声音问题
    安装win10笔记
    linux 时区问题
    JS实现网页飘窗
    缓存promise技术不错哦
    wepy相关
    生成keystore
    2017年终巨献阿里、腾讯最新Java程序员面试题,准备好进BAT了吗
    细思极恐-你真的会写java吗
    年终盘点:Java今年的大事记都在这里!
  • 原文地址:https://www.cnblogs.com/Sai0511/p/11307610.html
Copyright © 2011-2022 走看看