AT_abc230_f [ABC230F] Predilection 题解

发布时间 2023-11-14 16:52:46作者: carp_oier

prelogue

各位在比赛的时候一定要坚信自己的式子,然后去考虑自己的实现是不是挂了。本人在今天模拟赛的时候质疑自己的式子然后不看实现 100 -> 0。

analysis

考虑对这个给定数组进行前缀和,然后就将问题转化成为了求这个前缀和数组的子序列的个数。对于求子序列,我们很轻松可以写出来这个式子。

下面 \(pre\) 表示这个数字(前缀和)之前出现的位置。

\[f_i \gets \begin{cases}f_{i - 1} \times 2 + 1 & \mbox{if} & pre_i = 0\\ f_{i - 1} \times 2 - f_{pre_i - 1} & \mbox{if} & pre_i \neq 0\end{cases} \]

code time

read, ww 和 flush 是我的快读快写带的函数,含义大家应该都能想到吧。

喜提最优解 23ms。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rl register ll
#define fom(i, a) for(rl i=a; i; -- i)
#define foa(i, a, b) for(rl i=a; i < b; ++ i)
#define fos(i, a, b) for(rl i=a; i <= b; ++ i)
#define fop(i, a, b) for(rl i=a; i >= b; -- i)

const ll N = 5e5 + 10, P = 998244353;

ll n, a[N], f[N];

unordered_map<ll, ll> pre;

int main()
{
    read(n); fos(i, 1, n) read(a[i]), a[i] += a[i - 1]; 
    foa(i, 1, n) f[i] = ((f[i - 1] << 1 | 1) - (pre.find(a[i]) == pre.end() ? 0 : f[pre[a[i]] - 1] + 1) + P) % P, pre[a[i]] = i; ww(f[n - 1] + 1);
    return flush(), 0;
}