Educational Codeforces Round 81 B.

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. 首先考虑 "-1"的情况,如果sum[n] == 0,并且x的值在这个周期中(即sum[1]到sum[n])出现过,那么合法的答案就是无穷个,如果x没出现过答案就是 0
  2. 找到出整个周期,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 答案就可以加一
    其意义为某个位置的前缀和加上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;
}
发布了141 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/sinat_40872274/article/details/104133180