zoukankan      html  css  js  c++  java
  • LOJ #6433. 「PKUSC2018」最大前缀和(状压dp)

    题面

    LOJ #6433. 「PKUSC2018」最大前缀和

    题解

    这题有一定思维难度 ... (我就没想出来 , 靠大佬口胡的)

    不难发现 , 成为最大前缀和位置 (p) 后面的所有前缀都不能 (> 0) .

    如果可以 (>0) 那么后面必存在一点可以替换当前的答案 .

    有了这个思路 , 那我们可以把每个序列拆成两端考虑 , 而分割点就是位置 (p) .

    首先令 (sum_i)(i) 这个状态所有点的代数和 , 便于转移 .

    1. (f_{i})(i) 这个状态 满足 集合的最大前缀和 等于 集合和 (sum_i) 的方案数 .

      这个转移的话 , 我们考虑倒着插入数字 , 如果存在后缀这个 (sum_{suf} >0) 那么可以直接转移了 .

      因为这样构造 , 新得到的序列肯定比当前的更加优秀 . 转移方程就是

      [displaystyle k otin i ~mathrm{and}~ sum_i > 0 : f_i o f_{i+k} ]

    2. (g_i)(i) 这个状态 满足 所有前缀和(le 0) 的方案数 .

      这个容易转移一些 , 从前往后插入 , 每次填入的集合和都需要 (le 0) 就行了.

      [k otin i ~mathrm{and}~ sum_{i+k} le 0 : g_i o g_{i+k} ]

    有了这个答案就是 (sum sum_{i} imes f_i imes g_{mathrm{maxsta}-i}) .

    总时间复杂度就是 (O(n imes 2^n)) 然后我用 (O(2^n)) 求的 (sum) 数组 , 卡进了rank1 ...qwq

    代码

    #include <bits/stdc++.h>
    #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
    #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
    #define Set(a, v) memset(a, v, sizeof(a))
    using namespace std;
    
    inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
    inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
    
    inline int read() {
        int x = 0, fh = 1; char ch = getchar();
        for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
        for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
        return x * fh;
    }
    
    void File() {
    #ifdef zjp_shadow
    	freopen ("6433.in", "r", stdin);
    	freopen ("6433.out", "w", stdout);
    #endif
    }
    
    const int N = 21, inf = 0x7f7f7f7f, Mod = 998244353;
    int n, a[N], sum[1 << N], f[1 << N], g[1 << N], num[1 << N];
    
    #define lowbit(x) (x & -x)
    #define Add(a, b) if (((a) += (b)) >= Mod) (a) -= Mod
    
    int main () {
    	File();
    
    	n = read();
    	For (i, 0, n - 1) num[1 << i] = a[i] = read();
    
    	int maxsta = (1 << n) - 1;
    	For (i, 0, maxsta)
    		sum[i] = sum[i ^ lowbit(i)] + num[lowbit(i)];
    
    	g[0] = 1; 
    	For (i, 0, maxsta) if (sum[i] <= 0) 
    		For (j, 0, n - 1) if ((i >> j) & 1)
    			Add(g[i], g[i ^ (1 << j)]);
    	
    	For (i, 0, n - 1) f[1 << i] = 1;
    
    	int ans = 0;
    	For (i, 0, maxsta) {
    		if (sum[i] > 0)
    			For (j, 0, n - 1) if (!((i >> j) & 1))
    				Add(f[i | (1 << j)], f[i]);
    		Add(ans, (1ll * (sum[i] + Mod) * f[i] % Mod * g[maxsta ^ i] % Mod));
    	}
    			
    	printf ("%d
    ", ans);
    
    	return 0;
    }
    
  • 相关阅读:
    CesiumLab V1.1 新功能 (免费Cesium处理工具集)
    cesium 加载shp格式的白模建筑
    Cesium项目实战(3)-城市建筑三维白膜数据的制作与效果展示
    Tomcat内存优化
    ActiveMQ笔记(5):JMX监控
    mac机上搭建php56/nginx 1.8.x/thinkphp 3.2.x/gearman扩展/seaslog扩展/redis扩展环境
    大众点评cat系统的搭建笔记
    ActiveMQ笔记(4):搭建Broker集群(cluster)
    ActiveMQ笔记(3):基于Networks of Brokers的HA方案
    ActiveMQ笔记(2):基于ZooKeeper的HA方案
  • 原文地址:https://www.cnblogs.com/zjp-shadow/p/9141971.html
Copyright © 2011-2022 走看看