题目描述
给出长度为 \(N\) 的序列 \(A=(A_1,A_2,\dots,A_N)\) 以及一个整数 \(K\)。
存在 \(2^{N-1}\) 种方法将 \(A\) 分成若干个连续子区间。有多少划分方法满足没有任何一个划分出的子区间元素和为 \(K\)?请输出这个值模 \(998244353\) 的结果。
这里,“将 \(A\) 分成若干个连续子区间”的含义如下:
- 随意选择一个整数 \(k\space 1\le k\le N\) 作为序列长度,并且随意选择一个满足条件 \(1=i_1<i_2<\dots<i_k<i_{k+1}=N+1\) 的整数序列 \((i_1,i_2,\dots,i_k,i_{k+1})\)。
- 对于每个满足 \(1\le n\le k\) 的整数 \(n\),第 \(n\) 个被划分出来的子区间是由提取序列 \(A\) 中的第 \(i_n\) 到第 \((i_{n+1}-1)\) 个元素得到的。
举个例子,以下是序列 \(A=(1,2,3,4,5)\) 的若干可行划分方案:
- \((1,2,3),(4),(5)\)
- \((1,2),(3,4,5)\)
- \((1,2,3,4,5)\)
输入格式
从标准输入输出流输入,格式如下:
$ N \space K $
$ A_1 \space A_2 \space \dots \space A_N $
输出格式
请输出答案模 \(998244353\) 的结果。
输入输出样例 #1
输入 #1
3 3
1 2 3
输出 #1
2
输入输出样例 #2
输入 #2
5 0
0 0 0 0 0
输出 #2
0
输入输出样例 #3
输入 #3
10 5
-5 -1 -7 6 -6 -2 -5 10 2 -10
输出 #3
428
说明/提示
- \(1 \leq N \leq 2 \times 10^5\)
- \(-10^{15} \leq K \leq 10^{15}\)
- \(-10^9 \leq A_i \leq 10^9\)
- 全部输入为整数
对样例 1 的解释
以下是符合题目要求的 \(2\) 种划分方案。
- \((1),(2,3)\)
- \((1,2,3)\)
Author: Redshift_Shine
题解
设 \(F(x)\) 为长度为 \(x\) 的序列分为若干子序列的方法数,\(f(x)\) 为”没有任何一个划分出的子区间元素和为 \(K\) “的条件下的方法数。
对于 \(F(x)\),
当 \(x = 1\),
\((1)\)
当 \(x = 2\),
\((1) (2)\)
\((1, 2)\)
当 \(x = 3\),
\((1) (2) (3)\)
\((1) (2, 3)\)
\((1, 2) (3)\)
\((1, 2, 3)\)
通过朴素的观察,可以知道 x = 2 时的分类组合,可以看作时 x = 1 时的每个组合加上数字 2,再加上一个全集 \((1, 2)\)。同理 x = 3时的分类组合可以看作 x = 1 时的每一个组合加上数字 2, 3,x = 2 时的每一个组合加上数字 3,再加上一个全集\((1, 2 ,3)\)。
\(x = 2\)
\((1) \rightarrow (1, 2)\) // x = 1 的组合
\((1, 2)\)
\(x = 3\)
\((1) \rightarrow (1, 2, 3)\) // x = 1 的组合
(1) \((2) \rightarrow(1) (2) (3)\)
\((1, 2) \rightarrow (1, 2) (3)\) // x = 2 的组合
\((1, 2, 3)\)
即 \(F(i) = \sum_{j = 1} ^ {i - 1} F(j) + 1\) ,则 \(f(i) = \sum_{s_i-s_j \neq k}f(j) + (s_i==k?1:0)\) ,\(s_i-s_j\neq k\) 的条件过于离散,正难则反,\(f(i) = sum-\sum_{s_i-k}^{j}f(j)\),设 \(sum\) 是 \(1\) 到 \(i-1\) 的合理分配方法总和,设 \(B_i\) 是 \(sum\) 中的第 \(i\) 组合理分配,即\(B_i:b_1,b_2 \cdots, b_m\),则 \(B_i\) 加上 \(a_i\) 对应的分配方法 $ C_j \(是否符合条件,则需判断\) b_m + a_i = k$ 是否成立,即是否存在一个 j 满足 \(s_i - s_j = k\)。设 \(mp\) 记录每一个 \(s_i\) 对应的$ f_i$ 的和,\(f(i) = sum-mp[s_i-k]\)。\(s_i == k\) 也不符合条件,所以 \(mp[0] =1\)。
#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int mod = 998244353;
ll n, k, sum;
ll a[N], s[N];
map<ll, ll> mp;
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
mp[0] = 1, sum = 1;//空集也符合分配要求
for (int i = 1; i <= n; i++) {
f[i] = (sum - mp[s[i] - k] + mod) % mod;
mp[s[i]] = (mp[s[i]] + f[i]) %mod;
sum += f[i];
}
}