题意:
给定一个长度为
n
n
n 的数组
a
a
a,数组中每个数都是不大于
3
3
3 的正整数。已知一个区间的权值为该区间所有数乘积的因子数量,求所有区间的权值之和。答案对
1
e
9
+
7
1e9+7
1e9+7 取模。
数据范围:
1
≤
n
≤
1
0
5
1\leq n\leq 10^5
1≤n≤105
1
≤
a
i
≤
3
1\leq a_i\leq 3
1≤ai≤3
题解:
一个数
x
x
x 的因子数量为:
将
x
x
x 拆成所有质因子的乘积形式,统计每种质因子的个数,第
i
i
i 个质因子
p
i
p_i
pi 的数量为
c
n
t
p
i
cnt_{p_i}
cntpi
那么数
x
x
x 的因子数量为:
∏
i
=
1
(
c
n
t
p
i
+
1
)
\prod\limits_{i=1} (cnt_{p_i}+1)
i=1∏(cntpi+1)
p r e 2 i = ∑ j = 1 i [ a j = 2 ] pre2_i = \sum\limits_{j=1}^i [a_j=2] pre2i=j=1∑i[aj=2] , p r e 3 i = ∑ j = 1 i [ a j = 3 ] pre3_i = \sum\limits_{j=1}^i [a_j=3] pre3i=j=1∑i[aj=3]
p p r e 2 i = ∑ j = 1 i p r e 2 j ppre2_i = \sum\limits_{j=1}^i pre2_j ppre2i=j=1∑ipre2j, p p r e 3 i = ∑ j = 1 i p r e 3 j ppre3_i=\sum\limits_{j=1}^i pre3_j ppre3i=j=1∑ipre3j
m u l 2 3 i = ∑ j = 1 i p r e 2 j × p r e 3 j mul23_i = \sum\limits _{j=1}^{i}pre2_j\times pre3_j mul23i=j=1∑ipre2j×pre3j
对于题目中的区间权值,等价于 ( p r e 2 + 1 ) × ( p r e 3 + 1 ) (pre2+1)\times (pre3+1) (pre2+1)×(pre3+1)。
所以本题求的就是: ∑ r = 1 n ∑ l = 1 r ( p r e 2 r − p r e 2 l − 1 + 1 ) × ( p r e 3 r − p r e 3 l − 1 + 1 ) \sum\limits_{r=1}^{n}\sum\limits_{l=1}^{r} (pre2_r-pre2_{l-1}+1)\times (pre3_r-pre3_{l-1}+1) r=1∑nl=1∑r(pre2r−pre2l−1+1)×(pre3r−pre3l−1+1)
化简:
(
p
r
e
2
r
−
p
r
e
2
l
−
1
+
1
)
×
(
p
r
e
3
r
−
p
r
e
3
l
−
1
+
1
)
=
p
r
e
2
r
×
p
r
e
3
r
−
p
r
e
2
r
×
p
r
e
3
l
−
1
+
p
r
e
2
r
−
p
r
e
2
l
−
1
×
p
r
e
3
r
+
p
r
e
2
l
−
1
×
p
r
e
3
l
−
1
−
p
r
e
2
l
−
1
+
p
r
e
3
r
−
p
r
e
3
l
−
1
+
1
=
(
p
r
e
2
r
×
p
r
e
3
r
+
p
r
e
2
r
+
p
r
e
3
r
+
1
)
①
+
(
p
r
e
2
l
−
1
×
p
r
e
3
l
−
1
)
②
−
(
p
r
e
2
l
−
1
×
(
p
r
e
3
r
+
1
)
+
p
r
e
3
l
−
1
×
(
p
r
e
2
r
+
1
)
)
③
(pre2_r-pre2_{l-1}+1)\times (pre3_r-pre3_{l-1}+1) \\ =pre2_r\times pre3_r - pre2_r\times pre3_{l-1}+pre2_r-pre2_{l-1}\times pre3_r+pre2_{l-1}\times pre3_{l-1}-pre2_{l-1}+ pre3_r-pre3_{l-1}+1 \\ = (pre2_r\times pre3_r+pre2_r+pre3_r+1)_{①}+(pre2_{l-1}\times pre3_{l-1})_{②}-(pre2_{l-1}\times (pre3_r+1)+pre3_{l-1}\times (pre2_r+1))_{③}
(pre2r−pre2l−1+1)×(pre3r−pre3l−1+1)=pre2r×pre3r−pre2r×pre3l−1+pre2r−pre2l−1×pre3r+pre2l−1×pre3l−1−pre2l−1+pre3r−pre3l−1+1=(pre2r×pre3r+pre2r+pre3r+1)①+(pre2l−1×pre3l−1)②−(pre2l−1×(pre3r+1)+pre3l−1×(pre2r+1))③
对上述三个表达式分别求和:
①
∑
r
=
1
n
∑
l
=
1
r
(
p
r
e
2
r
×
p
r
e
3
r
+
p
r
e
2
r
+
p
r
e
3
r
+
1
)
=
∑
r
=
1
n
r
×
(
p
r
e
2
r
×
p
r
e
3
r
+
p
r
e
2
r
+
p
r
e
3
r
+
1
)
\sum\limits_{r=1}^{n}\sum\limits_{l=1}^{r} (pre2_r\times pre3_r+pre2_r+pre3_r+1)\\ =\sum\limits_{r=1}^{n} r\times (pre2_r\times pre3_r+pre2_r+pre3_r+1)
r=1∑nl=1∑r(pre2r×pre3r+pre2r+pre3r+1)=r=1∑nr×(pre2r×pre3r+pre2r+pre3r+1)
② ∑ r = 1 n ∑ l = 1 r ( p r e 2 l − 1 × p r e 3 l − 1 ) = ∑ r = 1 n m u l 2 3 r − 1 \sum\limits_{r=1}^{n}\sum\limits_{l=1}^{r} (pre2_{l-1}\times pre3_{l-1}) \\ = \sum\limits_{r=1}^{n}mul23_{r-1} r=1∑nl=1∑r(pre2l−1×pre3l−1)=r=1∑nmul23r−1
③ ∑ r = 1 n ∑ l = 1 r − ( p r e 2 l − 1 × ( p r e 3 r + 1 ) + p r e 3 l − 1 × ( p r e 2 r + 1 ) ) = − ∑ r = 1 n ∑ l = 1 r ( p r e 2 l − 1 × ( p r e 3 r + 1 ) + p r e 3 l − 1 × ( p r e 2 r + 1 ) ) = − ∑ r = 1 n ( p p r e 2 r − 1 × ( p r e 3 r + 1 ) + p p r e 3 r − 1 × ( p r e 2 r + 1 ) ) \sum\limits_{r=1}^{n}\sum\limits_{l=1}^{r} -(pre2_{l-1}\times (pre3_r+1)+pre3_{l-1}\times (pre2_r+1)) \\ =-\sum\limits_{r=1}^{n}\sum\limits_{l=1}^{r} \ (pre2_{l-1}\times (pre3_r+1)+pre3_{l-1}\times (pre2_r+1)) \\ =-\sum\limits_{r=1}^{n} (ppre2_{r-1}\times (pre3_r+1)+ppre3_{r-1}\times (pre2_r+1)) r=1∑nl=1∑r−(pre2l−1×(pre3r+1)+pre3l−1×(pre2r+1))=−r=1∑nl=1∑r (pre2l−1×(pre3r+1)+pre3l−1×(pre2r+1))=−r=1∑n(ppre2r−1×(pre3r+1)+ppre3r−1×(pre2r+1))
均可以在 O ( n ) O(n) O(n) 时间复杂度内完成。
代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int N = 100010;
int a[N], n;
int pre2[N], ppre2[N];
int pre3[N], ppre3[N];
int mul23[N];
void add(int& a, int b) {
a = (a + b) % mod;
if (a < 0) a += mod;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) {
pre2[i] = pre2[i - 1];
pre3[i] = pre3[i - 1];
if (a[i] == 2) {
add(pre2[i], 1);
} else if (a[i] == 3) {
add(pre3[i], 1);
}
ppre2[i] = ppre2[i - 1];
ppre3[i] = ppre3[i - 1];
add(ppre2[i], pre2[i]);
add(ppre3[i], pre3[i]);
mul23[i] = mul23[i - 1];
add(mul23[i], 1ll * pre2[i] * pre3[i] % mod);
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
int temp = 0;
add(temp, 1ll * pre2[i] * pre3[i] % mod);
add(temp, pre2[i]);
add(temp, pre3[i]);
add(temp, 1);
add(ans, 1ll * i * temp % mod);
add(ans, -1ll * (1 + pre3[i]) * ppre2[i - 1] % mod);
add(ans, -1ll * (1 + pre2[i]) * ppre3[i - 1] % mod);
add(ans, mul23[i - 1]);
}
printf("%d\n", ans);
return 0;
}