LOJ #6433. 「PKUSC2018」最大前缀和(状压dp)

题面

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

题解

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

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

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

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

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

  1. fii 这个状态 满足 集合的最大前缀和 等于 集合和 sumi 的方案数 .

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

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

    ki and sumi>0:fifi+k

  2. gii 这个状态 满足 所有前缀和0 的方案数 .

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

    ki and sumi+k0:gigi+k

有了这个答案就是 sumi×fi×gmaxstai .

总时间复杂度就是 O(n×2n) 然后我用 O(2n) 求的 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\n", ans); return 0; }

__EOF__

本文作者zjp_shadow
本文链接https://www.cnblogs.com/zjp-shadow/p/9141971.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zjp_shadow  阅读(999)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示