题目链接
题意:
给定一序列
a
1
,
a
2
,
…
,
a
n
a_1, a_2, \dots , a_n
a1,a2,…,an,若连续子序列
a
l
,
a
l
+
1
,
a
l
+
2
,
…
,
a
r
−
1
,
a
r
a_l, a_{l+1}, a_{l+2}, \dots , a_{r-1}, a_r
al,al+1,al+2,…,ar−1,ar满足
∑
i
=
l
r
a
i
=
r
−
l
+
1
\sum\limits_{i=l}^{r} a_i = r - l + 1
i=l∑rai=r−l+1,称为
g
o
o
d
good
good序列,求
g
o
o
d
good
good序列的数量。
思路:
我们考虑求序列
a
1
,
a
2
,
…
,
a
n
a_1, a_2, \dots , a_n
a1,a2,…,an的前缀和
S
1
,
S
2
,
S
3
,
…
,
S
n
S_1,S_2,S_3,\dots,S_n
S1,S2,S3,…,Sn其中
S
k
=
∑
i
=
1
k
a
i
S_k=\sum\limits_{i=1}^{k} a_i
Sk=i=1∑kai,那么要使得
∑
i
=
l
r
a
i
=
r
−
l
+
1
\sum\limits_{i=l}^{r} a_i = r - l + 1
i=l∑rai=r−l+1等价于
S
r
−
S
l
−
1
=
r
−
(
l
−
1
)
S_r-S_{l-1}=r-(l-1)
Sr−Sl−1=r−(l−1)即
S
r
−
r
=
S
l
−
1
−
(
l
−
1
)
S_r-r=S_{l-1}-(l-1)
Sr−r=Sl−1−(l−1)由题意显然
l
≤
r
l\le r
l≤r即
l
−
1
<
r
l-1<r
l−1<r。故题求序列数量即统计每一个
S
i
−
i
S_i-i
Si−i的数量,通过map或者直接数组统计数量并计算组合数即可,当然计算组合数这个过程可以放到统计数量的过程中去;但是,我们同时注意到对于1这种特殊情况,第一次出现就可以记为一个
g
o
o
d
good
good序列了,所以在最开始初始化其数量为1即可。
AC代码:
#include <bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
int T = 1;
int main() {
cin>>T;
while (T--) {
int n;
ll ans=0;
string str;
cin>>n>>str;
vector<ll> sum(n+1);
map<ll,ll> ma;
sum[0]=0;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+str[i-1]-'0';
ma[0]=1;
for(int i=1;i<=n;i++){
ans+=ma[sum[i]-i];
ma[sum[i]-i]++;
}
cout<<ans<<endl;
}
return 0;
}