定义: 乘积等于和的区间为合法区间
根据数据范围分析“积”与“和”的情况
a
i
a_i
ai的范围是1~200000,
n
n
n的范围是1~200000,则区间和的最大值等于最大区间长度
×
\times
× 元素的可取最大值
=
200000
×
200000
<
2
36
= 200000\times 200000<2^{36}
=200000×200000<236, 将一个区间内大于
1
1
1 的数的个数记为
t
o
t
tot
tot,那么对于任意一个合法区间都满足
t
o
t
<
36
tot < 36
tot<36
一个区间的的乘积显然
≥
2
t
o
t
\geq 2^{tot}
≥2tot;当一个区间的
t
o
t
≥
36
tot\geq 36
tot≥36 或者说乘积大于等于
200000
×
200000
200000\times 200000
200000×200000 时该区间不是合法区间
定义
s
u
m
[
i
]
sum[i]
sum[i] 表示
a
1
+
a
2
+
⋯
+
a
i
a_1+a_2+\cdots+a_i
a1+a2+⋯+ai,区间
[
L
,
R
]
[L,R]
[L,R] 的和用
s
u
m
[
R
]
−
s
u
m
[
L
−
1
]
sum[R]-sum[L-1]
sum[R]−sum[L−1] 得到了。
步骤
1、将大于
1
1
1 的元素的下标按顺序记录在
v
e
c
t
o
r
vector
vector 里,然后枚举区间左端点。确定了左端点后再从
v
e
c
t
o
r
vector
vector 里枚举合法区间的右端点,这样枚举的总复杂度不超过
O
(
n
×
36
)
O(n\times 36)
O(n×36)。
2、设枚举的左端点为
L
L
L,右端点为
R
R
R,那么区间的和为
s
u
m
[
R
]
−
s
u
m
[
L
−
1
]
sum[R]-sum[L-1]
sum[R]−sum[L−1],区间的乘积我们也可以在枚举右端点过程中求出(记乘积值为
n
o
w
now
now)。
3、要使区间合法,需满足
s
u
m
[
R
]
−
s
u
m
[
L
−
1
]
=
n
o
w
sum[R] - sum[L-1] = now
sum[R]−sum[L−1]=now。而如果
s
u
m
[
R
]
−
s
u
m
[
L
−
1
]
<
n
o
w
sum[R] - sum[L-1] < now
sum[R]−sum[L−1]<now,则我们需要在不影响区间乘积值的情况下,右移区间(即添加
n
o
w
−
(
s
u
m
[
R
]
−
s
u
m
[
L
−
1
]
)
now - (sum[R] - sum[L-1])
now−(sum[R]−sum[L−1]) 个值为
1
1
1 的元素)
4、记录每个大于
1
1
1 的元素后面有多少个值为
1
1
1 的连续的元素。 记每个大于
1
1
1 的元素后有
s
u
f
suf
suf 个连续的
1
1
1,那么只要满足
n
o
w
≤
s
u
m
[
R
]
−
s
u
m
[
L
−
1
]
+
s
u
f
now \leq sum[R]-sum[L-1] + suf
now≤sum[R]−sum[L−1]+suf 即可通过右移区间使得区间合法。
如果 s u m [ R ] − s u m [ L − 1 ] > n o w sum[R]-sum[L-1] > now sum[R]−sum[L−1]>now,显然在不改变 n o w now now 的情况下我们是无法使区间合法的。
INF = 40000000000
n = int(input())
array = list(map(int,input().split()))
suf = [0 for _ in range(n+2)]
vec = []
sumlist = [0 for _ in range(n+2)]
tot = 0
index = 0
while index < n:
if array[index] > 1:
vec.append(index)
tot += 1
sumlist[index] = sumlist[index-1] + array[index]
index += 1
res = 0
cnt = 0
for i in range(n-1,-1,-1):
if array[i] > 1:
suf[i] = cnt
cnt = 0
else:
cnt += 1
index = 0
while index < n:
res +=1
now = array[index]
L = 0
R = tot - 1
pos = n
while L <= R:
mid = L + R >> 1
if vec[mid] > index:
R = mid - 1
pos = mid
else:
L = mid + 1
j =pos
while j < tot:
now *=array[vec[j]]
if now > INF:
break
sumof = sumlist[vec[j]]-sumlist[index-1]
if sumof <= now and \
now <= sumof + suf[vec[j]]:
res += 1
j+=1
index += 1
print(res)