首页 > 其他分享 >P5369 [PKUSC2018] 最大前缀和

P5369 [PKUSC2018] 最大前缀和

时间:2024-01-27 22:13:04浏览次数:35  
标签:前缀 val int PKUSC2018 cin P5369

[PKUSC2018] 最大前缀和

Luogu P5369

题目描述

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

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

小 C 是一个非常有自知之明的人,他知道自己的算法完全不对,所以并不关心正确率,他只关心求出的解的期望值,现在请你帮他解决这个问题,由于答案可能非常复杂,所以你只需要输出答案乘上 \(n!\) 后对 \(998244353\) 取模的值,显然这是个整数。

注:最大前缀和的定义:\(\forall i \in [1,n]\),\(\sum_{j=1}^{i}a_j\)的最大值。

Solution

考虑一个位置上的值想要成为最大前缀和需要满足什么条件。不难发现这个位置开始之后所有位置的前缀和都应该为非正数,且这个位置开始之前的所有位置的前缀和都应该为非负数。那么只要想办法 DP 出来前半段的方案数 \(f\) 和后半段的方案数 \(g\) 然后相乘即可。

这个 DP 方法类似 CF327E。设 \(f(S)\) 表示当前选定数的集合为 \(S\) 的所有前缀和都非正的方案数。那么转移的时候只需要判断 \(x+\displaystyle\sum\limits_{v\in S} v\) 是否非正即可。\(g\) 的转移同理。

最后枚举在前半段的集合 \(t\),设全集为 \(U\),那么答案即为 \(\displaystyle\sum\limits_{t\subseteq U}g(t)\times f(\complement_Ut)\)。

时间复杂度 \(\mathcal O(n2^n)\)。

Code
int N, A[_N];
int val[_M];
mint f[_M], g[_M];
signed main() {
    cin.tie(0)->sync_with_stdio(0);
    cin >> N;
    For(i, 1, N) cin >> A[i];
    int lim = 1 << N;
    For(S, 0, lim - 1) {
        For(i, 1, N) if (S >> (i - 1) & 1)
            val[S] += A[i];
    }
    f[0] = g[0] = 1;
    For(S, 0, lim - 1) {
        For(i, 1, N) if (!(S >> (i - 1) & 1)) {
            if (val[S] >= 0 || S == 0) f[S|(1<<(i-1))] += f[S];
            if (A[i] + val[S] < 0) g[S|(1<<(i-1))] += g[S];
        }
    }
    mint ans = 0;
    For(S, 1, lim - 1) {
        mint tmp = (val[S] % mod + mod) % mod;
        ans += tmp * f[S] * g[(lim-1)^S];
    }
    cout << ans << '\n';
}

标签:前缀,val,int,PKUSC2018,cin,P5369
From: https://www.cnblogs.com/hanx16msgr/p/17992150

相关文章

  • 前缀和与差分典题
    includeusingnamespacestd;constintN=1010;inta[N][N],b[N][N];voidinsert(intx1,inty1,intx2,inty2,intc){b[x1][y1]+=c;b[x2+1][y1]-=c;b[x1][y2+1]-=c;b[x2+1][y2+1]+=c;}intmain(){intn,m,q,w;scanf("%d%d%d",&n,&m,&......
  • CF467C George and Job 题解 DP 前缀和
    DP前缀和题目链接题意:给你一个长度为\(n\)的序列,让你从这个序列中挑选出\(k\)个长度为\(m\)的区间,并且任意区间不相交。使得选出的数之和最大,求出这个数。解法:很经典的DP模型,我们定义\(f_{i,j}\)表示从前\(i\)个数选出了\(j\)个区间可以取得的最大值,那么答案为:\(f_{n,k}\)。......
  • 路由策略(前缀列表,策略工具-filter-policy,策略工具-Router-policy,双点双向路由重发布)
    1.前缀列表默认是拒绝,如果没写允许,就都是拒绝Greater-equal26less-equal32从子网掩码26-32被匹配,其他的被拒绝2.策略工具1:filter-policy(过滤策略)Export只对引入的路由,,对引入的路由在过滤,是不是发给我的邻居使用,import对所有路由器都可用*ospf:import*R1传......
  • nginx 替换访问路径前缀
    可以使用nginx的rewrite模块来替换访问路径前缀。例如,将所有以“/api”开头的请求转发到后端服务器,并将“/api”替换为“/backend”,可以在nginx配置文件中添加以下规则: location/api{rewrite^/api(.*)$/backend$1break;proxy_passhttp://backend-server;} 这样,当......
  • 求前缀表达式的值
    #include<iostream>#include<algorithm>#include<string>#include<stack>#include<stdlib.h>usingnamespacestd;stack<double>st;intmain(){stringstr[100];intn=0;//在求前缀或者后缀的时候,从前到后读入数据,前缀的话倒着读出数据,从右往左看,有数......
  • 从CF1878E学习前缀和维护二进制拆位分析思想
    Problem-1878E-Codeforces这题我想到了个大概,按位与的话结果肯定是递减的,而且要从二进制每一位下手,但是思路只停留在暴力对整个数操作。当然,利用这个性质,肯定要二分。拆位思想比如要计算111000111011100100010我们知道最后结果肯定是留下都有\(1\)的位0100000......
  • js用前缀名查找class或id节点,js模糊查询某个dom节点
     1//参数dom为htmldom节点2//参数key为需模糊查询的名称字段3functionqueryClassNode(dom,key){4letcollectArray=[];5for(leti=0;i<dom.childNodes.length;i++){6//核心点7if(d......
  • 浅谈C++简单前缀和实现
    浅谈前缀和2023.9.28\(tips:\)文章持续更新中,欢迎关注\(upd:\)文章从洛谷博客迁移至博客园(\(2024.1.19\))洛谷B3612【深进1.例1】求区间和题目大E:有一个内部元素个数为\(n\)的数组\(a\),现在有m次询问,求a[l]到a[r]之间所有元素的和朴素的做法:#include<iostream>usin......
  • 刷题 位运算异或 异或前缀和
    2024.1.18杭州电子科技大学2023华为杯编程竞赛 解题思路首先可以知道,我们任意选一点为根root往下递归异或就可以得到f[i](root到i的路径异或值),那么 l到r的路劲异或值可以由f[l]^f[r]得出那么如何计算答案呢,就是用f[l]~f[r]分别异或f[x]......
  • 算法—前缀和
    1.一维前缀和S[i]=a[1]+a[2]+...a[i]//求s[n]a[l]+...+a[r]=S[r]-S[l-1]//求l-r的序列和2.二维前缀和S[i,j]=s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];第i行j列格子左上部分所有元素的和以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的和为:S[......