P5369 [PKUSC2018] 最大前缀和 题解
题目大意
给定一个序列,求任意重排 中情况所以的最大非空前缀和的和。模 。
,
题目解析
考虑最大前缀和的性质,有:
对于最大前缀和部分,所有的 真 后缀大于等于零。(最大前缀和可能小于零)
对于不在最大前缀和的后半部分,所有的前缀和小于等于零。
证明略去,显然。
所以对于前后两部分 分开 状压 DP 即可。
先考虑后半部分。
从后往前选。设 表示选了 这些数字的方案数量。
那么
当然需要保证 。
然后考虑前半部分。
从前向后选。
考虑到真后缀这个限制。
设 表示选了 这些数字,所有后缀/所有真后缀 大于等于零的方案数。
有
答案显然,就是
为全集。
时间复杂度
#define maxn 1200039 #define MOD 998244353 int n,m,a[39],p[maxn]; ll f[maxn][2],g[maxn],s[maxn]; int main(){ fin>>n; m=(1<<n)-1; int i,j; ll ans=0; for(i=0;i<n;i++){ fin>>a[i],p[1<<i]=i; if(a[i]>=0) f[1<<i][0]=1; else f[1<<i][1]=1; } for(i=1;i<=m;i++) s[i]=s[i^(i&-i)]+a[p[i&-i]]; g[0]=1; for(i=0;i<=m;i++) for(j=0;j<n;j++) if(!(i&(1<<j))){ if(a[j]+s[i]>=0) f[i|(1<<j)][0]+=f[i][0],f[i|(1<<j)][0]%=MOD; else f[i|(1<<j)][1]+=f[i][0],f[i|(1<<j)][1]%=MOD,g[i|(1<<j)]+=g[i],g[i|(1<<j)]%=MOD; } for(i=1;i<=m;i++) ans+=(s[i]%MOD+MOD)%MOD*(f[i][1]+f[i][0])%MOD*g[m^i]%MOD,ans%=MOD; fin<<ans<<'\n'; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具