首页 > 其他分享 >abc288

abc288

时间:2023-02-05 22:55:05浏览次数:51  
标签:tmp limits int sum times num abc288

C:

如果当前连的边和以前连的形成了环,就任意删除一条边,并查集维护。

E:

首先需要知道,若考虑购买当前物品 \(i\) ,那么设之前买了 \(j\) 个了,那么可以在 \(c_{i-j+1} \sim c_i\) 之间任意时刻购买,取最小值即可,用 st 表维护。

F:

首先容易发现一个 \(O(n^2)\) 的做法。设 \(f_{i}\) 表示前 \(i\) 个数字分段之后的乘积和,有:

\[f_i = \sum\limits_{0\le j<i}(f_j \times num_{j+1, i}) \]

其中 \(num_{l,r}\) 表示区间 \([l,r]\) 表示的数字。
形式的说

\[num_{l,r} = \sum\limits_{i=l}^ra_i\times10^{r-i} \]

那么怎么优化呢?
用 \(sum\) 表示 \(\sum\limits_{j=1}^i\),\(tmp\) 表示 \(\sum\limits_{0\le j<i}(f_j \times num_{j+1, i})\),
容易发现一个递推的式子
\(tmp = tmp\times 10 + a_i\times sum\)
这里的 \(sum\) 是考虑到 \(i-1\) 时的 \(sum\)。
于是复杂度优化到 \(O(n)\) 了。

短短 16 行代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, P = 998244353;
int n, a[N], dp[N] = {1}, sum = 1, tmp = 0;
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%1d", &a[i]);
	for (int i = 1; i <= n; i++) {
		tmp = (tmp * 10ll + a[i] * 1ll * sum) % P;
		dp[i] = (dp[i] + tmp) % P;
		sum = (sum + dp[i]) % P;
	}
	printf("%d\n", dp[n]);
	return 0;
}

标签:tmp,limits,int,sum,times,num,abc288
From: https://www.cnblogs.com/Vancezyx/p/17094136.html

相关文章