首页 > 其他分享 >CF1810G The Maximum Prefix 题解

CF1810G The Maximum Prefix 题解

时间:2024-08-27 23:05:38浏览次数:11  
标签:kMod 前缀 int 题解 CF1810G kMaxN Prefix bs dp

Description

构造一个长度最多为 \(n\) 的数组 \(a\),其每个元素均为 \(1\) 或 \(-1\)。生成方式如下:

  • 选择任意整数 \(k\in[1,n]\) 作为 \(a\) 的长度。
  • 对于 \(\forall i\in[1,k]\),有 \(p_i\) 的概率设 \(a_i=1\),有 \(1-p_i\) 的概率设 \(a_i=-1\)。

在数列被生成后,计算 \(s_i=a_1+a_2+a_3+...+a_i\)。特别地,\(s_0=0\)。此时 \(s\) 数组的最大前缀和 \(S=max_{i=0}^ks_i\)。

现在给定 \(n+1\) 个正整数 \(h_0,h_1,...,h_n\)。\(a\) 数组最大前缀和 \(S\) 的分数为 \(h_s\)。现在,对于每个 \(k\),你要求出一个数组长度为 \(k\) 的期望分数对 \(10^9+7\) 取模的结果。

\(n\leq 5000\)。

Solution

先考虑给定数组怎么快速求最大前缀和。

显然可以直接求出每个前缀和,再取最大值,但是这样要记两个变量,很难放在 dp 里面。

另一个做法是倒着扫,维护 \(s\) 表示当前扫过的后缀的最大前缀和,每次让 \(s\leftarrow \max\{s+a_i,0\}\) 即可。

放到本题可以暴力枚举要求答案的前缀,设 \(f_{i,j}\) 表示当前倒着扫到了 \(i\),目前的最大前缀和为 \(j\) 的概率,可以得到转移:\(f_{i,j+1}\leftarrow p_if_{i+1,j},f_{i,\max\{j-1,0\}}\leftarrow (1-p_i)f_{i+1,j}\)。

最后 \(\sum f_{1,i}h_i\) 就是答案。

时间复杂度:\(O(n^3)\)。


这个做法慢在 dp 时要枚举前缀的后缀,dp 状态会很冗余。

考虑怎么正着扫做 dp。

先把这题状态转移的 DAG 建出来,每次相当于是求从一个点开始往后走的期望权值。由于不同前缀的 DAG 是一样的,所以可以让转移边反过来跑期望 dp。

具体的,设 \(g_{i,j}\) 表示从末尾已经考虑到了 \(i+1\),当前最大前缀和为 \(j\) 的期望权值。可以的得到转移:\(g_{i,j}=p_ig_{i-1,j+1}+(1-p_i)g_{i-1,\max\{j-1,0\}}\)。

边界条件是 \(g_{0,i}=h_i\),对于前缀 \([1,i]\) 的答案即为 \(g_{i,0}\)。

时间复杂度:\(O(n^2)\)。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 5e3 + 5, kMod = 1e9 + 7;

int n;
int p[kMaxN], h[kMaxN], f[kMaxN][kMaxN];

constexpr int qpow(int bs, int64_t idx = kMod - 2) {
  int ret = 1;
  for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)
    if (idx & 1)
      ret = (int64_t)ret * bs % kMod;
  return ret;
}

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }

void dickdreamer() {
  std::cin >> n;
  for (int i = 1; i <= n; ++i) {
    int x, y;
    std::cin >> x >> y;
    p[i] = 1ll * x * qpow(y) % kMod;
  }
  for (int i = 0; i <= n; ++i) std::cin >> h[i];
  for (int i = 0; i <= n; ++i) f[0][i] = h[i];
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= n; ++j) {
      f[i][j] = add(1ll * p[i] * f[i - 1][j + 1] % kMod, 1ll * sub(1, p[i]) * f[i - 1][std::max(j - 1, 0)] % kMod);
    }
    std::cout << f[i][0] << ' ';
  }
  std::cout << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:kMod,前缀,int,题解,CF1810G,kMaxN,Prefix,bs,dp
From: https://www.cnblogs.com/Scarab/p/18383703

相关文章

  • NOI2024 D1T3 口胡题解
    NOI2024D1T3口胡题解题目条件其实就是说对于点对\((a,b)\),从\(a\)到\(b\)的路径上至少要有一条从\(b\)指向\(a\)​的边。将初始状态记作\((T,S)\)​,其中\(T\)​是树,\(S\)​是二元组\((a,b)\)​的集合。注意到特殊性质A蕴含了:如果对于所有二元组\((a,b)\),\(a......
  • [COCI2012-2013#1] SNAGA 题解
    前言题目链接:洛谷。题意简述定义\(f(x)\)表示不能整除\(x\)的最小正整数。给出数字\(n\),每次\(n\getsf(n)\),当\(n=2\)时停止。定义\(g(n)\)为这一过程中的数字个数,例如\(g(6)=4\)。给定\(l,r\),求\(\sum\limits_{i=l}^rg(i)\)。\(3\leql\ltr......
  • 【题解】「CQOI2014」通配符匹配
    【题解】「CQOI2014」通配符匹配https://www.luogu.com.cn/problem/P3167令\(s\)为模式串,\(t\)为文本串。首先有一个显然的的dp是,\(f_{i,j}\)表示模式串的前\(i\)个和文本串的前\(j\)个是否匹配。显然\(O(n^2)\)是过不了的。Motivation:注意到题目限定了通配符......
  • CF645D - Robot Rapping Results Report 题解
    \[Problem\]有\(N\)个机器人,给出\(M\)组关系,表示两个机器人的能力关系,问至少需要前几组关系可以确定所有机器人的排名。\[Solution\]由于是求最少的前几组关系,而关系越少越难确定排名,关系越多越容易确定,不难发现本题满足单调性,考虑二分。那么给出关系要求总排名的题,就应该......
  • AT_code_festival_2017_qualc_d - Yet Another Palindrome Partitioning 题解
    YetAnotherPalindromePartitioning题解题目大意给出一个字符串,求把这个字符串划分成最少的小段,使每个小段都可以经过字母重组后为回文串。题目分析如果暴力的话,需要DFS段数、每一段的左节点、右节点,以及判断是否为回文串,时间复杂度在\(O(|S|^{|S|})\)左右。但是本......
  • Dirsearch-master安装使用及常见问题解决(互联网和内网)
    1、文档概述        本手册适用于帮助初学者快速掌握Dirsearch-master的安装、配置与使用方法。通过阅读本文档,您将能够了解如何搭建Dirsearch-master环境、扫描目标服务器上潜在的敏感文件和目录,并解读生成的报告。此外,本文档还涵盖了常见问题及解决方法,以便您在实际......
  • 【题解】P3210 [HNOI2010] 取石头游戏
    \(\large\mathfrak{1st.\Preamble|}\)前言题目传送门:P3210[HNOI2010]取石头游戏)主要是参考楼下大佬的题解,对于其中没讲到或比较难懂的地方进行讲解,以及配上了图。\(\large\mathfrak{2nd.\Solution|}\)题解楼下大佬的比喻十分形象生动地描绘了俩人去石头的过程:取石子......
  • 题解:P10922 Happybob's Numbers (UBC001B)
    主要思路:贪心,构造。思路构造题,首先明确要删的就是小于\(n\)的数,因为若删了大于等于\(n\)的数就无法进行之后的操作了。那这道题就简单了,先从大到小排序,遇到小于当前长度\(k\)的数,就将这个数删掉,这时长度需减\(1\),毕竟顺序可以自己调,将下一个小于当前\(k\)的数,放到下一......
  • 题解:P5934 [清华集训2012] 最小生成树
    主要思路:网络流。思路先考虑最小生成树,如果一条边边权大于等于选中的边,那么这条边是否删去没有任何影响。按边权排序,对于边\((u,v,L)\),若要加上当且仅当\(u\)和\(v\)并不联通。把所有边权比选定的边的边权小的边拿出来连上,流量均为\(1\),最小割。最大树同理,连上边权比选......
  • 题解:P11007 『STA - R7』Odtlcsu
    评价:简单构造。思路注意题目中的“如果有多解输出任意一种即可”。由于\(a\)与\(a^{2}\)的奇偶性必定是一致的,所以我们可以将情况分为两种。当\(x\)与\(y\)奇偶性不一致时,但由于\(a\)与\(a^{2}\)的奇偶性必定是一致的,所以始终无法构造出正确的序列。但注意题目......