Written with StackEdit.

Description

小\(C\)是一个算法竞赛爱好者,有一天小\(C\)遇到了一个非常难的问题:求一个序列的最大子段和。

但是小\(C\)并不会做这个题,于是小\(C\)决定把序列随机打乱,然后取序列的最大前缀和作为答案。

小\(C\)是一个非常有自知之明的人,他知道自己的算法完全不对,所以并不关心正确率,他只关心求出的解的期望值,

现在请你帮他解决这个问题,由于答案可能非常复杂,所以你只需要输出答案乘上\(n!\)后对\(998244353\)取模的值,显然这是个整数。

Input

第一行一个正整数\(n\),表示序列长度。

第二行\(n\)个数,表示原序列\(a[1..n]\),第\(i\)个数表示\(a[i]\)。

\(1≤n≤20,Sigma(|A_i|)<=10^9\),其中\(1<=i<=N.\)

Output

输出一个非负整数,表示答案。

Sample Input

2

-1 2

Sample Output

3

Solution

  • 注意到\(n\)很小,每个子集的权值和我们可以暴力计算得出.
  • 直接考虑各个子集作为最大前缀和.
  • 显然,一个子集\(S\)排列后能成为最大前缀和,那么这个排列中不能有负的后缀和(否则去掉会更优),剩下的数排列后不能有正的前缀和(否则加上会更优).
  • 我们令\(f[S]\)表示将\(S\)集合中的数排成没有负的后缀和的排列的方案数,\(g[S]\)表示将\(S\)集合中的数排成没有正的前缀和的排列的方案.
  • 那么易知答案即为\(\sum_{S\in U,sum[S]>=0}f[S]*g[\complement_{U}S]*sum[S]\).
  • 考虑如何快速计算出\(f\)和\(g\).若对于一个集合\(i\),新增了一个数\(j\).(\(j\notin i\)).
  • 我们可以将\(i\)任意排列,再将\(j\)放在最后,方案数为\(f[i]\)或\(g[i]\),统计入贡献.每个集合中的每个数都会被放在最后转移过来,所以总贡献一定是正确的.
  • 这样,只需要在加数的时候判断一下\(sum[i]\)的符号,即可确定转移\(f\)或\(g\).
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
{
fh=-1;
jp=getchar();
}
while (jp>='0'&&jp<='9')
{
out=out*10+jp-'0';
jp=getchar();
}
return out*fh;
}
const int P=998244353;
const int MAXS=(1<<20)+10;
inline int add(int a,int b)
{
return (a + b) % P;
}
inline int mul(int a,int b)
{
return 1LL * a * b % P;
}
int a[21];
int sum[MAXS],f[MAXS],g[MAXS];
int n;
inline int calc(int S)
{
int res=0;
for(int i=0;i<n && S;++i,S>>=1)
if(S&1)
res+=a[i];
return res;
}
int main()
{
n=read();
for(int i=0;i<n;++i)
a[i]=read();
int S=1<<n;
for(int i=0;i<S;++i)
sum[i]=calc(i);
for(int i=0;i<n;++i)
f[1<<i]=1,g[1<<i]=1;
for(int i=0;i<S;++i)
{
if(sum[i]>0)
{
for(int j=0;j<n;++j)
if(!((i>>j)&1))
f[i^(1<<j)]=add(f[i^(1<<j)],f[i]);
}
else
{
for(int j=0;j<n;++j)
if(!((i>>j)&1))
g[i^(1<<j)]=add(g[i^(1<<j)],g[i]);
}
}
int ans=0;
int U=S-1;
g[0]=1;
for(int i=0;i<S;++i)
if(sum[U^i]<=0)
ans=add(ans,mul(mul(f[i],sum[i]),g[U^i]));
printf("%d\n",add(ans,P));
return 0;
}

bzoj 5369 最大前缀和的更多相关文章

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

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

  2. 【BZOJ4391】[Usaco2015 dec]High Card Low Card(贪心)

    [BZOJ4391][Usaco2015 dec]High Card Low Card(贪心) 题面 BZOJ 题解 预处理前缀后缀的结果,中间找个地方合并就好了. #include<iostr ...

  3. 【BZOJ3555】企鹅QQ(字符串哈希)

    [BZOJ3555]企鹅QQ(字符串哈希) 题面 BZOJ 题解 把前缀哈希一下,后缀哈希一下 枚举哪个位置不选,然后检查一下相同就行了.. 为什么我的\(Hash\)老是\(WA\), 为什么\(Z ...

  4. BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)

    BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...

  5. Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和

    下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...

  6. BZOJ 4236 "JOIOJI"(前缀和+map+pair)

    传送门: [1]:BZOJ [2]:洛谷 •题解 定义数组 a,b,c 分别表示 'J' , 'O' , 'I' 的前缀和: 要想使区间 (L,R] 满足条件当且仅当 a[R]-a[L] = b[R] ...

  7. BZOJ 1218: [HNOI2003]激光炸弹(二维前缀和)

    Description 一种新型的激光炸弹,可以摧毁一个边长为R的正方形内的所有的目标.现在地图上有n(N<=10000)个目标,用整数Xi,Yi(其值在[0,5000])表示目标在地图上的位置 ...

  8. 【BZOJ】1202: [HNOI2005]狡猾的商人(并查集+前缀和)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1202 用并查集+前缀和. 前缀和从后向前维护和,并查集从前往后合并 对于询问l, r 如果l-1和r ...

  9. BZOJ 1218: [HNOI2003]激光炸弹( 前缀和 + 枚举 )

    虽然source写着dp , 而且很明显dp可以搞...但是数据不大 , 前缀和 + 枚举也水的过去..... -------------------------------------------- ...

随机推荐

  1. 【JavaScript】canvas实现一个小游戏

    参考: 1.image onload事件:http://www.runoob.com/jsref/event-img-onload.html(赞) 2.canvas的drawImage无法显示图像:h ...

  2. Sybase:SybaseIQ的几个系统过程

    Sybase:SybaseIQ的几个系统过程 sp_iqlocks 显示与数据库中 IQ 存储区和目录存储区中的锁有关的信息. 删除锁:drop connection XXX sp_iqwho 显示所 ...

  3. Python3.x:日期库dateutil简介

    Python3.x:日期库dateutil简介 安装 pip install python-dateutil 关于parser #字符串可以很随意,可以用时间日期的英文单词,可以用横线.逗号.空格等做 ...

  4. 物理机内存模型与java内存模型

    多线程缓存一致性问题 程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数 ...

  5. 新机git及github sshkey简单配置

    新机git简单配置,毕竟不常用,不用每次都查1.安装gitwindows:https://git-scm.com/download/winubuntu: apt install git 2.全局配置 ...

  6. 《Maven实战》第5章 坐标和依赖

    5.1 Maven坐标——项目唯一标识 groupId(必须定义):定义Mavan项目隶属的实际项目,如SpringFramework,一个实际项目可包含多个Maven项目 artifactId(必须 ...

  7. jquery中ajax回调函数使用this

    今天在写ajax请求的的时候success中代码老是不能正常执行,找了半天的原因,代码如下: 1 $.ajax({type: 'GET', 2 url: url, 3 data: oData, 4 s ...

  8. idea技巧

    写在前面 以前一直用的elipce,如今入坑IntelliJ IDEA,没想到啊.深深的爱上了它,强大到无所不能: "工欲善其事必先利其器",IntelliJ IDEA作为一个非常 ...

  9. codevs.cn 2776寻找代表元 最大流解法

    网址:http://codevs.cn/problem/2776/ 题目大意: n个社团,m个人,每个社团可以有一个人担任代表,每个人可以担任多个代表,问最多有多少人是代表. 思路:可以建一个图,然后 ...

  10. quartz(6)--集群

    Quartz应用能被集群,是水平集群还是垂直集群取决于你自己的需要.集群提供以下好处: · 伸缩性 · 高可用性 · 负载均衡 目前,Quartz只能借助关系数据库和JDBC作业存储支持集群. qua ...