题目链接:洛谷

题目大意:给定一个长为$n$的整数序列,求全排列的最大前缀和(必须包含第一个数)之和。

数据范围:$1\leq n\leq 20,1\leq \sum_{i=1}^n|a_i|\leq 10^9$


神级状压dp,不得不服。。。

我们考虑对全排列的最大前缀和的前缀的集合进行dp。

设$f[S],g[S]$分别表示集合$S$内的数组成的排列中,最大前缀和为$sum[S]$和负数的排列数,其中$sum[S]$为$\sum_{i\in S}i$

我们发现,如果这个最大的前缀组成的集合就是$S$,当且仅当前$|S|$个数的最大前缀和为$sum[S]$,后面$n-|S|$个数的最大前缀和为负数,所以

$$ans=\sum_{S\subset U}sum[S]*f[S]*g[U-S]$$

其中$U$表示全集。注意这里$g[S]$必须要求是负数才可以,0不行,否则可能会重复统计。

然后考虑对$f,g$进行dp。

若$sum[S]\geq 0$,则$g[S]=0$,否则枚举最后一个数$j$,即$g[S]=\sum_{j\in S}g[S-\{j\}]$

若$sum[S]\geq 0$,则对于$j\notin S$,$f[S+\{j\}]+=f[S]$,否则$f[S]$对$f[S+\{j\}]$无贡献。

时间复杂度$O(n2^n)$,空间复杂度$O(2^n)$

 #include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = << , mod = ;
int n, lim, sum[N], f[N], g[N], ans;
inline int add(int a, int b){int c = a + b; return c >= mod ? (c - mod) : c;}
int main(){
scanf("%d", &n); lim = << n; g[] = ;
for(Rint i = ;i < n;i ++){
scanf("%d", sum + ( << i));
f[ << i] = ;
}
for(Rint i = ;i < lim;i ++)
sum[i] = add(sum[i ^ (i & -i)], sum[i & -i]);
for(Rint i = ;i < lim;i ++)
if(sum[i] >= ){
for(Rint j = ;j < n;j ++)
if(!(i & ( << j))) f[i | ( << j)] = add(f[i | ( << j)], f[i]);
} else {
for(Rint j = ;j < n;j ++)
if(i & ( << j)) g[i] = add(g[i], g[i ^ ( << j)]);
}
for(Rint i = ;i < lim;i ++)
ans = add(ans, (LL) sum[i] * f[i] % mod * g[lim - - i] % mod) % mod;
printf("%d", (ans % mod + mod) % mod);
}

Luogu5369

Luogu5369 [PKUSC2018]最大前缀和的更多相关文章

  1. [PKUSC2018]最大前缀和

    [PKUSC2018]最大前缀和 题目大意: 有\(n(n\le20)\)个数\(A_i(|A_i|\le10^9)\).求这\(n\)个数在随机打乱后最大前缀和的期望值与\(n!\)的积在模\(99 ...

  2. BZOJ_5369_[Pkusc2018]最大前缀和_状压DP

    BZOJ_5369_[Pkusc2018]最大前缀和_状压DP Description 小C是一个算法竞赛爱好者,有一天小C遇到了一个非常难的问题:求一个序列的最大子段和. 但是小C并不会做这个题,于 ...

  3. [PKUSC2018]最大前缀和——状压DP

    题目链接: [PKUSC2018]最大前缀和 设$f[S]$表示二进制状态为$S$的序列,任意前缀和都小于等于$0$的方案数. 设$g[S]$表示二进制状态为$S$的序列是整个序列的最大前缀和的方案数 ...

  4. LOJ6433 [PKUSC2018] 最大前缀和 【状压DP】

    题目分析: 容易想到若集合$S$为前缀时,$S$外的所有元素的排列的前缀是小于$0$的,DP可以做到,令排列前缀个数小于0的是g[S]. 令f[S]表示$S$是前缀,转移可以通过在前面插入元素完成. ...

  5. BZOJ5369:[PKUSC2018]最大前缀和(状压DP)

    Description 小C是一个算法竞赛爱好者,有一天小C遇到了一个非常难的问题:求一个序列的最大子段和. 但是小C并不会做这个题,于是小C决定把序列随机打乱,然后取序列的最大前缀和作为答案. 小C ...

  6. BZOJ5369 [Pkusc2018]最大前缀和

    题意 小C是一个算法竞赛爱好者,有一天小C遇到了一个非常难的问题:求一个序列的最大子段和. 但是小C并不会做这个题,于是小C决定把序列随机打乱,然后取序列的最大前缀和作为答案. 小C是一个非常有自知之 ...

  7. bzoj 5369: [Pkusc2018]最大前缀和

    Description 小C是一个算法竞赛爱好者,有一天小C遇到了一个非常难的问题:求一个序列的最大子段和. 但是小C并不会做这个题,于是小C决定把序列随机打乱,然后取序列的最大前缀和作为答案. 小C ...

  8. [PKUSC2018]最大前缀和(DP)

    题意:求一个序列随机打乱后最大前缀和的期望. 考场上发现不管怎么设状态都写不出来,实际上只要稍微转换一下就好了. 一个前缀[1..k]是最大前缀,当且仅当前面的所有后缀[k-1,k],[k-2,k], ...

  9. P5369 [PKUSC2018]最大前缀和

    状态压缩 P5369 题意:求所有排列下的最大前缀和之和 一步转化: 求最大前缀和的前缀由数集S组成的方案数, 统计答案时直接乘上sum(S)即可 考虑最大前缀和的性质: 设最大前缀和为sum[i] ...

随机推荐

  1. IDEA GIT 忽略文件 最佳方式

    前言 转载一篇博客,简单,实用. 原文地址:intellij idea 忽略文件不提交 ps:下面均为转载博客的内容: 在intellij中忽略提交文件,分两种情况, 文件没有纳入版本管理 第一种,文 ...

  2. ggalluvial|TCGA临床数据绘制桑基图(Sankey)

    本文首发于”生信补给站“,https://mp.weixin.qq.com/s/yhMgkST-rVD6SaQS7R-eoA 桑基图(Sankey diagram),是一种特定类型的流程图,图中延伸的 ...

  3. sping+redis实现消息队列的乱码问题

    使用spring支持redis实现消息队列,参考官方样例:https://spring.io/guides/gs/messaging-redis/ 实现后在运行过程中发现消费者在接收消息时会出现乱码的 ...

  4. R语言做逻辑回归

    前面写过一个多分类的逻辑回归,现在要做一个简单的二分类,用glm函数 导入csv格式如下: mydata<-read.csv("D://li.csv",header=T) c ...

  5. Ctrl+R快速启动应用程序

    1.打开注册表 Ctrl+R搜索框中键入“regedit”,回车打开注册表 2.找到HKEY_LOCAL_MACHINE中的如下路径 HKEY_LOCAL_MACHINE\SOFTWARE\Micro ...

  6. 微软升级 WSL Window Subsystem for Linux Win10系统自带Linux

    在设计之初,微软就允许类似于Win32这种子系统运行于windows NT内核之上,它可以为上层应用提供编程接口,同时避免应用去实现内核里的一些调用细节.NT内核的设计在最开始就可以支持POSIX,O ...

  7. 听课笔记--DP--最大子矩阵和

    最大子矩阵问题 给定一个n*n(0<n<=120)的矩阵, 矩阵内元素有正有负, 请找到此矩阵的内部元素和最大的子矩阵 样例输入: 4 0 -2 -7  0  9  2 -6  2  -4 ...

  8. trape 一种识别工具

    trape是一种识别工具,可以让你跟踪任何人,你可以得到的信息非常详细.通过去识别现有的网站所登录的用户,来追踪一个人的虚拟身份 如何使用它首先卸载工具.git clone https://githu ...

  9. C语言字符串格式化输出

    %ms:将字符串全部输出,如果字符串长度小于m,在左边用空格将输出宽度补齐为m: %.ns:如果n大于字符串长度,将字符串全部输出,否则,输出前n个字符: %m.ns:如果n不大于m,输出指定字符串的 ...

  10. lvs+keepalived+application部署(只使用两台机器)

    目前大家用LVS+Keepalived + APP 架构都是 2台LVS +Keepalived 然后后端跟着 应用设备 然而针对小客户来说,  2台LVS平常没什么压力 还有一台备着(虽然可以跑双主 ...