题目描述
给出的是一个长度为 N N N的序列 A A A,你可以做任何次数的操作:当序列的长度至少为2时,选择两个相邻的值,删除它们,并在它们原来的位置插入它们的和。有多少个序列可以从零或更多的操作中产生?对答案取998244353的模数。
样例与解释
Sample 1
input、
3
1 -1 1
output、
4
Explanation、
The following four sequences can result from zero or more operations.
`1,−1,1
`1,0
`0,1
`1
Sample 2
input 、
4
1 -1 1 -1
output、
7
Explanation、
The following seven sequences can result from zero or more operations.
1 -1 1 1
1 0 1
0 1 1
1 1
·····················································
1 -1 2
1 1 (has been exist)
0 2
2
题解
理解题意后,很容易可以想到是递推。
假设当前的序列长度为3 如 Sample 1 中所示,
那么显然答案为3,
f
(
3
)
=
=
3
f(3)==3
f(3)==3 。
当我们在该序列的后面插入一个新的数字1后,就如Sample 2 所示,答案为7,即
f
(
4
)
=
=
7
f(4)==7
f(4)==7。
不难发现,Sample 1 是 Sample 2 的前缀部分,也就是说,Sample 2 的答案是可以由 Sample 1 递推而来。
观察 Sample 2 的合法序列,发现序列 (1 ,-1,1,1)、(1,0,1)、(0,1 ,1)以及(1,1)都是由 Sample 1 的合法序列后面接上 Sample 2 新加入的数得来。而序列(1,-1,2)、(1,1)、(0,2)、(2)都是把新加入的数字1,并入 Sample 1 中合法序列的最后一个元素得来,其中(1,1)发生了重复,要减去,所以,答案就是7。
得出大概的递推柿子
f
(
i
)
=
f
(
i
−
1
)
×
2
−
重
复
部
分
f(i)=f(i-1) \times 2 - 重复部分
f(i)=f(i−1)×2−重复部分
考虑重复部分,应该减去什么?
对于 Sample 2 和 Sample 1 来说,为什么 Sample 2 的 (1,1) 序列会在上文中提到的两种递推方式中被重复计算。
因为第一递推方式中的(1,1)是由 Sample 1 中的 (1)末尾接上一个1得来的,而第二种递推方法中的 (1,1)是由 Sample 1中的 (1,0)的末尾元素加上1得来的。
而这其实是Sample 2 (1,-1,-1,1)中的-1和第三个1(1,<-1,1>,1)合并后产生的0,在最终再合并给了第一个1,或者最后一个1所导致的结果。由于0在加法运算中是弱势元,所以两种合并方法结果是一样的。假设当前递推到
i
i
i位 ,从
i
−
1
i-1
i−1位 开始,往前找,找到最大的
j
j
j,满足
s
e
q
(
a
1
,
a
2
,
a
3
.
.
.
,
a
j
,
.
.
.
,
a
i
−
1
)
,
Σ
(
a
j
.
.
.
a
i
−
1
)
=
0
seq(a_1,a_2,a_3...,a_j,...,a_{i-1}), \Sigma(a_j...a_{i-1})=0
seq(a1,a2,a3...,aj,...,ai−1),Σ(aj...ai−1)=0
此时对于
f
(
i
)
f(i)
f(i)来说
f
(
j
−
1
)
f(j-1)
f(j−1)就是重复部分。
为什么要找最大的
j
j
j?因为之前有些连续元素合并后产生0所造成的重复已经在计算
f
(
j
)
f(j)
f(j)时被减去了,因此不必再计算了。
我们只要处理后缀和,当
j
j
j位和
i
i
i 位的后缀和相同时,就说明满足上面的条件。
官方题解||我的代码