CodeForces - 1295B Infinite Prefixes(数学)

题目链接:点击查看

题目大意:给出一个由0或1组成的字符串s,用来构造出字符串 t =  s + s + s....+ s,字符串 t 由无限个 s 拼接而成。现在规定cnt_0 [ i ]和cnt_1 [ i ]分别为到第 i 位为止所出现的0和1的个数,给出一个 x ,问字符串 t 中有多少个前缀满足cnt_0 [ i ] - cnt_1 [ i ] == x,若有无限个答案,输出-1

题目分析:简单到不能在简单的数学题了,但是比赛的时候脑子瓦特了,一直处理不了细节,加上读题的时候就把心态读崩了,正所谓是半小时读题,一秒钟出正解,一小时debug,然后交上去1WA,心态直接炸裂,完成掉分

读完题后,第一反应应该是有一个公式的,因为字符串 t 是由字符串 s 无限循环而得到的,每次循环后都必定会有数字0和数字1差值积累的贡献,比如字符串101,每循环一次所积累的差值为 -1 ,循环100次积累的差值就是 -100 ,所以我们可以分为两类,一类是可以积累贡献的,另一类是不能积累贡献的(也就是0的个数和1的个数相同时),当然输出-1的情况显然在不能积累贡献的情况中,我们假设找到 x 时是在第 k 次循环,那么有公式:

k * ( cnt_0 [ n ] - cnt_1 [ n ] ) + ( cnt_0 [ i ] - cnt_1 [ i ] ) == x 

移项处理得到:

k * ( cnt_0 [ n ] - cnt_1 [ n ] ) == x - ( cnt_0 [ i ] - cnt_1 [ i ] )

满足上述条件的 i 就是我们所要找的答案了,需要满足两个条件:

  1. 因为积累贡献的 k 是从 0 开始的,所以第一个条件为(x - ( cnt_0 [ i ] - cnt_1 [ i ] )) / ( cnt_0 [ n ] - cnt_1 [ n ] ) >=0
  2. 其次就是 (x - ( cnt_0 [ i ] - cnt_1 [ i ] )) / ( cnt_0 [ n ] - cnt_1 [ n ] ) == 0

当然众所周知 0 不能作为除数出现,所以要分类讨论一下( cnt_0 [ n ] - cnt_1 [ n ] ) == 0时的情况,也就是不能积累贡献的情况,还有空串的情况也需要特判

代码:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;

const int N=1e5+100;

int cnt[N];

char s[N];

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		int n,x;
		scanf("%d%d%s",&n,&x,s+1);
		for(int i=1;i<=n;i++)
		{
			cnt[i]=cnt[i-1];
			if(s[i]=='0')
				cnt[i]++;
			else
				cnt[i]--;
		}
		int ans=0;
		if(x==0)//特判空串 
			ans++;
		for(int i=1;i<=n;i++)
		{
			if(cnt[n]==0)//每次循环贡献为0 
			{
				if(cnt[i]==x)
					ans++;
			}
			else//每次循环都有贡献 
			{
				if((x-cnt[i])%cnt[n]==0&&(x-cnt[i])/cnt[n]>=0)
					ans++;
			} 
		}
		if(cnt[n]==0&&ans)//特判无限
			ans=-1;
		printf("%d\n",ans);
	}
 
 
 
 
 
	
	
	
	
	
	
	
	
	
	return 0;
}
发布了577 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104111765