题目链接:洛谷

题目大意:给定一个长为$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. Message高级特性

    一.延迟和定时消息投递 1 xml中配置schedulerSupport属性为true 2 每小时都会发生消息被投递10次,延迟1秒开始,每次间隔1秒: TextMessage message = s ...

  2. Abp 领域事件简单实践 <三> 自定义事件

    熵片用到的  EntityCreatedEventData<TEntity>,继承自EventData. 我们可以自定义事件: public class TestEvent: EventD ...

  3. SVN配置使用及移植

    使用svn作为配置管理工具及其普遍的用于项目开发中,网上有很多关于svn的原理介绍及命令行管理教程.这里仅仅分享下个人配置及使用的过程,不通过命令行,可简单的上手操作.如有遗漏欢迎留言交流. 配置及使 ...

  4. c#开启线程池超出索引

    这样写会超出索引,foreach好像不会超出,原因可能是开启线程池需要时间,成功开启之后,一次循环已经结束,这个没有验证. 以下这个做法是不对的,我也是看网上的贴这样写,结果是少执行了一个.推荐大家还 ...

  5. SpringCloud各个组件通俗解析

    https://www.cnblogs.com/lonelyJay/p/9936241.html

  6. ln -s vs mount --bind

    First ,Symlinks and bind mounts are a whole different ballgame. ln -s you create a symbolic link,whi ...

  7. java - day008 - 接口,内部类

    接口 作用: 结构设计工具,用来解耦合,需要有子类,隔离具体实现 接口是一个极端的抽象类 用 interface 代替 class 用 implements 代替 extends // 接口中所有东西 ...

  8. docker从入门到精通再到放弃

    docker说明 docker三大功能:构建(build).运输(ship).运行(run),只需要记下这三大功能就可以了 1.docker入门 docker安装及配置 a.docker源配置 cur ...

  9. Error creating bean with name 'objectMapperConfigurer' defined in class path resource

  10. PAT Basic 1080 MOOC期终成绩 (25 分)

    对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,必须首先获得不少于200分的在线编程作业分,然后总评获得不少于60分( ...