B.Infinite Prefixes
链接:https://codeforces.com/contest/1295/problem/B
【题意】
给一个长度为 n 的 0-1 字符串 Str ,找出所有Str的所有前缀子串中,满足 字符0个数 - 字符1个数 = x 的子串个数,输出答案,如果答案为无穷多则输出 “-1”
【思路】
sum[i] 是Str中01字符个数的差值的前缀和,即Str的前 i 个字符中, 字符0个数 - 字符1个数的个数
分类讨论:
- 首先考虑 "-1"的情况,如果sum[n] == 0,并且x的值在这个周期中(即sum[1]到sum[n])出现过,那么合法的答案就是无穷个,如果x没出现过答案就是 0
- 找到出整个周期,sum[i]值的变化量(即经历了一个周期后 sum[i]的变化),其实就是sum[n]。
当满足
( x − s u m [ i ] ) / s u m [ n ] > = 0 a n d ( x − s u m [ i ] ) m o d s u m [ n ] = = 0 (x - sum[i])/sum[n] >= 0\ \ and\ \ (x -sum[i]) \mod sum[n] == 0 (x−sum[i])/sum[n]>=0 and (x−sum[i])modsum[n]==0答案就可以加一
其意义为某个位置的前缀和加上n个周期的贡献为x,同时要保证周期次数大于等于0次
/*****************************
*author:ccf
*source:cf_ER 81 B. Infinite Prefixes
*topic:
*******************************/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#define ll __int64
using namespace std;
const int N = 1e5+7;
ll n,cas,x;
int main(){
freopen("data.in","r",stdin);
scanf("%I64d",&cas);
char str[N];
ll sum[N],ans,flag;
while(cas--){
scanf("%I64d %I64d",&n,&x);
scanf("%s",str+1);
memset(sum,0,sizeof sum);
ans= 0,flag = 0;
for(int i = 1; i <= n; ++i){
if(str[i] == '0') sum[i] = sum[i-1]+1;
else sum[i] = sum[i-1]-1;
if(sum[i] == x) flag = 1;
}
if(x == 0) ++ans;
if(sum[n] == 0){
if(flag) printf("-1\n");
else printf("%I64d\n",ans);
continue;
}
for(int i = 1; i <= n; ++i)
if((x - sum[i])/sum[n] >= 0 && (x -sum[i]) % sum[n] == 0) ans++;
printf("%I64d\n",ans);
}
return 0;
}