[PKUSC2018]最大前缀和

题目大意:

有\(n(n\le20)\)个数\(A_i(|A_i|\le10^9)\)。求这\(n\)个数在随机打乱后最大前缀和的期望值与\(n!\)的积在模\(998244353\)意义下的值。其中最大前缀和的定义为\(\forall i\in[1,n]\sum_{j=1}^iA_j\)的最大值。

思路:

考虑一个分界点\(p\),使得\(\sum A_{1\sim p}\)为最大前缀和,那么显然\(p\)之后的所有前缀和均\(<0\),否则就存在可以替换\(p\)的方案使得前缀和更大。

用\(sum[i]\)表示子集\(i\)的数值和,\(f[i]\)表示最大前缀和为\(sum[i]\)的方案数,\(g[i]\)表示任意前缀和均为负的方案数。\(f[i]\)和\(g[i]\)均可以通过动态规划求得。最后答案即为\(\sum sum[S]\times f[S]\times g[\overline S]\)。时间复杂度\(\mathcal O(2^nn)\)。

源代码:

#include<cstdio>
#include<cctype>
typedef long long int64;
inline int getint() {
register char ch;
register bool neg=false;
while(!isdigit(ch=getchar())) neg|=ch=='-';
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return neg?-x:x;
}
const int N=20,mod=998244353;
int a[N],f[1<<N],g[1<<N];
int64 sum[1<<N];
int main() {
const int n=getint(),u=(1<<n)-1;
g[0]=1;
for(register int i=0;i<n;i++) {
f[1<<i]=1;
a[i]=getint();
for(register int s=0;s<1<<n;s++) {
if(s&(1<<i)) sum[s]+=a[i];
}
}
for(register int s=1;s<1<<n;s++) {
if(sum[s]>0) {
for(register int i=0;i<n;i++) {
if(!(s&(1<<i))) {
(f[s|(1<<i)]+=f[s])%=mod;
}
}
} else {
for(register int i=0;i<n;i++) {
if(s&(1<<i)) {
(g[s]+=g[s^(1<<i)])%=mod;
}
}
}
}
int ans=0;
for(register int i=1;i<1<<n;i++) {
(ans+=(int64)sum[i]*f[i]%mod*g[u^i]%mod)%=mod;
}
printf("%d\n",(ans+mod)%mod);
return 0;
}

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

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

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

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

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

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

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

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

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

  5. BZOJ5369 [Pkusc2018]最大前缀和

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

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

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

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

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

  8. P5369 [PKUSC2018]最大前缀和

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

  9. 【洛谷5369】[PKUSC2018] 最大前缀和(状压DP)

    点此看题面 大致题意: 对于一个序列,求全排列下最大前缀和之和. 状压\(DP\) 考虑如果单纯按照题目中对于最大前缀和的定义,则一个序列它的最大前缀和是不唯一的. 为了方便统计,我们姑且规定,如果一 ...

随机推荐

  1. typeof的用法

    typeof可以返回变量的类型,返回值为字符串,其值有 "undefined" "boolean" "string" "numbe ...

  2. linux系统引导流程

    1.固件:硬件和软件结合.加电自检是我们按下电源会检测硬件像cpu.内存.网卡等信息.(从硬件层次检测硬件是否可用) 固件设置实例:设置时间 软件时间和硬件时间: [root@VM_0_12_cent ...

  3. 【Matlab】绘制饼状统计图

    a=tabulate(b); % b为需要绘制饼图的原始数据列,生成新的一个矩阵a label={'1','2','3'} % 设定饼图每块扇形代表的内容 percent=num2str(a(:,3) ...

  4. glom模块的使用(一)

    glom模块的使用 简单说下glom模块主要是处理结构化数据用的,安装简单pip install glom即可,下面就glom的方法参数做例子讲解. glom 和模块同名的glom方法使用方法: .g ...

  5. mysql 1366的错误 字符集错误解决方案

    最近用mysqlalchmy的时候遇到了 sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1366, "Incorrec ...

  6. 用pyperclip 模块拷贝粘贴字符串

    >>> import pyperclip>>> pyperclip.copy('Hello world!')>>> pyperclip.paste ...

  7. sicily 1036. Crypto Columns

    Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description The columnar encryption scheme scram ...

  8. 2017多校第8场 HDU 6134 Battlestation Operational 莫比乌斯反演

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6134 题意: 解法: 那么g(n)怎么求,我们尝试打表发现g(n)是有规律的,g(n)=g(n-1)+ ...

  9. c语言中数组,指针数组,数组指针,二维数组指针

    1.数组和指针 ] = {,,,,};// 定义数组 // 1. 指针和数组的关系 int * pa = array; pa = array; // p[0] == *(p+0) == array[0 ...

  10. P4819 [中山市选]杀人游戏

    题目描述 一位冷血的杀手潜入Na-wiat,并假装成平民.警察希望能在NN个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民.假如查 ...