首页 > 其他分享 >CodeForces 1810G The Maximum Prefix

CodeForces 1810G The Maximum Prefix

时间:2023-07-24 15:45:53浏览次数:56  
标签:1810G 前缀 res ll typedef long CodeForces Prefix maxn

洛谷传送门

CF 传送门

感觉是比较 educational 的题。

拿到题目应该有一个大致思路,就是考虑最大前缀和的求法,再把它扔到状态里面。

最大前缀和有两种求法:

  • 从前往后求,需要维护当前前缀和 \(s\),当前最大前缀和 \(mx\),需要记录两个变量,无法承受。
  • 从后往前求,只需记录当前最大前缀和 \(mx\),从 \([i + 1, n]\) 的最大前缀和转移到 \([i, n]\) 的最大前缀和时,我们贪心地判断 \(a_i\) 是否属于最大前缀和,即 \(mx \gets \max(mx + a_i, 0)\)。

于是我们有一个初步的 dp 思路:设 \(f_{i, j}\) 为当前考虑了 \([i, n]\),其最大前缀和为 \(j\)。有转移:

\[\begin{cases} p_i f_{i + 1, j} \to f_{i, j + 1} \\ (1 - p_i) f_{i + 1, j} \to f_{i, \max(j - 1, 0)} \end{cases} \]

初值为 \(f_{n + 1, 0} = 1\),最终 \(ans = \sum\limits_{i = 0}^n h_i f_{1, i}\)。

我们算的只是长度为 \(n\) 的答案,我们希望对于每个长度 \(l\) 都求出答案,但是直接做是 \(O(n^3)\) 的。

注意到我们每次 dp 的转移都是固定的,只是初值不同(长度为 \(l\) 时 dp 初值为 \(f_{l + 1, 0} = 1\)),因此 \(f_{i, j}\) 对答案的贡献也是固定的。我们不妨使用反推贡献系数的 trick,设 \(g_{i, j}\) 为 \(f_{i, j}\) 对 \(ans\) 的贡献系数,那么有转移:

\[g_{i + 1, j} = p_i g_{i, j + 1} + (1 - p_i) g_{i, \max(j - 1, 0)} \]

初值为 \(g_{1, i} = h_i\)。最终长度为 \(l\) 的答案为 \(g_{l + 1, 0}\)。

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

code
// Problem: G. The Maximum Prefix
// Contest: Codeforces - CodeTON Round 4 (Div. 1 + Div. 2, Rated, Prizes!)
// URL: https://codeforces.com/problemset/problem/1810/G
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 5050;
const ll mod = 1000000007;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, p[maxn], f[maxn][maxn], a[maxn];

void solve() {
	scanf("%lld", &n);
	for (int i = 1, x, y; i <= n; ++i) {
		scanf("%d%d", &x, &y);
		p[i] = 1LL * x * qpow(y, mod - 2) % mod;
	}
	for (int i = 0; i <= n; ++i) {
		scanf("%lld", &a[i]);
		f[1][i] = a[i];
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 0; j <= n; ++j) {
			f[i + 1][j] = ((j < n ? f[i][j + 1] : 0) * p[i] % mod + f[i][max(j - 1, 0)] * (mod + 1 - p[i]) % mod) % mod;
		}
	}
	for (int i = 2; i <= n + 1; ++i) {
		printf("%lld ", f[i][0]);
	}
	putchar('\n');
}

int main() {
	int T = 1;
	scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:1810G,前缀,res,ll,typedef,long,CodeForces,Prefix,maxn
From: https://www.cnblogs.com/zltzlt-blog/p/17577388.html

相关文章

  • 「题解」Codeforces Round 887 (Div. 2)
    A.DesortingProblem题目Sol&Code若序列一开始无序答案为\(0\)若有序即\(a_1\leqa_2\leq\dots\leqa_n\)。若想让\(a_i>a_j(i<j)\),操作次数与两数差值\(d(d=a_j-a_i)\)相关为\(\lfloor\dfrac{d}{2}\rfloor+1\),差值越小操作次数越少,故枚举相邻两数取最少......
  • Codeforces Round 887 (Div. 2)
    C.Ntarsis'Set​ (\(1\leqn,k\leq2\cdot10^5\))题解:思维+二分我们不妨反向考虑由于答案最后一次一定在第一个位置所以答案上一轮一定在第一个空的位置,假设这个位置为\(x\)那么如果说要使得答案在位置\(x\),那么上上一轮答案一定在第\(x\)个空的位置我们可以......
  • Codeforces Round 887 (Div 2) C. Ntarsis' Set
    Ntarsis'Set题意是给你n个数,每次按照顺序删除位于a[i]位置的这n个数,问k次后最小的是多少参考这位大佬的题解CodeforcesRound887(Div2)A~C-知乎(zhihu.com)结合一个官方题解,进行一次操作后,由于前面删掉i个数,a[i]到a[i+1]间所有数的排名都要-=i,那么在a[i]到a[i+1]之间的......
  • 【题解】Educational Codeforces Round 151(CF1845)
    VP战报:1h过了A,B,C,D然后被E罚坐1hrank:210th题解只有A-EA.ForbiddenInteger题目描述:你需要构造一个正整数序列,满足:对于\(i\),\(a_i\lek\)且\(a_i\not=x\)。\(\suma_i=n\)。如无法构造,输出NO,否则输出YES后,输出序列长度与序列中的每一个数。多测\(t\le......
  • Codeforces Round 886 (Div. 4) 题解 A - H
    A.ToMyCritics题目大意给定三个数,你可以挑俩数加起来,问这仨数有没有可能加起来大于等于\(10\).解题思路我们找其中最大的两个数相加与\(10\)比较即可。ACCode#include<iostream>#include<algorithm>#include<cstring>#defineendl'\n'#defineiosios::sync......
  • Codeforces Round 886 (Div. 4) 全题题解
    我关注的人中正式参与比赛排名公示:#Who=Penalty*ABCDEFGH1(980)Chen_Jinhui7381\(\color{#00CC00}{\textbf{+}}\)00:05\(\color{#00CC00}{\textbf{+1}}\)00:17\(\color{#00CC00}{\textbf{+}}\)00:19\(\color{#00CC00}{\textbf{+}}\)01:08......
  • Codeforces Round 886 (Div. 4)记录
    A-ToMyCritics代码:#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#include<string.h>#include<set>#include<string>#include<map>#include<iostream>#include<queue>#in......
  • Codeforces Round 885 (Div. 2) A - C
    A.VikaandHerFriendsProblem-A-Codeforces题意:​ 在\(n*m\)的范围内,\(a\)和她的朋友在追逐游戏,每秒\(a\)和朋友必须从当前位置移到相邻的格子里(上下左右),在这一秒结束时\(a\)不能和朋友在同一格内。现在知道\(a\)和每一个朋友的初始位置,问\(a\)是否会被朋友追上。思路:......
  • Codeforces Round 886 (Div. 4)补题
    CodeforcesRound886(Div.4)A~D://A:boolsolve(){ cin>>a[1]>>a[2]>>a[3]; sort(a+1,a+4); returna[2]+a[3]>=10?1:0;}//B:voidsolve(){ intn; cin>>n; intmaxa=0; intnum=0; intx,y; for(inti=1;i<=n;i++){cin>......
  • Codeforces Round 886 (Div. 4)
    F.WeWereBothChildren题解:约数我们先利用\(map\)记录\(a_i\)的出现次数然后对\(map\)中的每一个元素的在其所有不超过\(n\)的倍数的位置上都加上对应的贡献时间复杂度:调和级数\(O(nlogn)\)constintN=2e5+10,M=4e5+10;intn;inta[N];map<int,int>......