Codeforces1295B Infinite Prefixes (思维)

题目连接: Infinite Prefixes

2021.9.2 我以前写博客真逗

题目:

题目版本1:已知长度为n的字符串s,由0和1组成。小明总会构建一个无限字符串t,作为无限个字符串s的串联,即t=ssss…例如,如果s= 10010,那么t= 100101001010010…
题目定义一个平衡值x。平衡的字符串q满足cnt(0,q) - cnt(1,q) = x,即Q中0 的个数 - Q中1的个数= x。这样的前缀可以无限的数量;如果是这样的话,你必须这样说。
前缀是由给定字符串的几个首字母组成的字符串,没有任何重新排序。空前缀也是有效的前缀。例如,字符串“abcd”有5个前缀:空字符串、“a”、“ab”、“abc”和“abcd”。

题目版本2:给定由0,1组成的字符串s,长度为n,定义t = sssssss…一个无限长的字符串。
题目定义一个平衡值x,取t的任意前缀Q,如果Q满足cnt(0,q) - cnt(1,q) = x,即Q中0 的个数-1的个数= x,说明当前的Q是满足题意得一个前缀,问满足x的前缀有多少个, 如果x = ∞,则输出-1.

Input
有T组输入,接下来2T行,每两行是一组测试样例。
第一行包含两个整数n(1<=n<=1e5),x(-1e9<=x<=1e9),分别表示字符串长度,平衡值x。
注意:n1 + n2 + n3 + … + nT<=1e5,即n的总和不超过10^5。

Output
打印T行答案,对于每组样例,如果平衡前缀是有限的,则输出数量,如果平衡前缀是无线的,则输出-1.

Example
Input
4
6 10
010010
5 3
10101
1 0
0
2 0
01
Output
3
0
1
-1

注: 本题翻译有点捉急, 看不懂多看看, 尽量去理解(或者去看英文版).

解题思路:

大体拆分下来其实结果无非两种, 一种是有限解情况, 而另一种是无限解情况.
1.无限解: 其实不难得出结果, 如果解是无穷的, 那么一定这个串内0和1的数量相等, 且一定存在这个串的一个子串(或该串本身)的0与1差值与x值相同. 只有这样才是无穷解的情况.
2.有限解: 若x减去当前位置0和1差值所得的结果k, 刚好为若干个(或0个)整字符串之和, 此时便为所求解.
用数学表达就是 x - (0与1差值) = k; k要满足 k % (该串0和1总差值) =0
如果理解还是有困难不妨对照代码看看

AC代码:

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#define ll long long
using namespace std;
int b[1000000];//用于存储当前位置0和1差值
int main(void)
{
	int t; cin >> t;
	while (t--) {
		int odd = 0, even = 0; int res = 0; //odd和even记录串内0和1的个数 res记录结果

		int n; int x; cin >> n >> x;
		string a; cin >> a;
		int length = a.length(); //其实可以直接用n

		for (int i = 0; i < length; i++) {
			if (a[i] == '0') even++;
			else odd++;
			b[i] = even - odd;
 		}

		/* 判断无穷 */
		if (b[length - 1] == 0) {
			bool flag = false;
			for (int i = 0; i < length; i++) {
				if (b[i] == x) { flag = true; break; }
			}
			if (flag) { printf("-1\n"); continue; } //无穷解
			else { printf("0\n"); continue; } //至于这里为什么是无解, 你不妨仔细想想, 
		}						/* 这个串0和1总差值是0, 且串内01差值还没有与x值相等的, 何来解? */

		if (x == 0) res++; //由于空前缀也是一种解, 所以不要忘了当x==0的时候 啥都没有也是解
		for (int i = 0; i < length; i++) {
			if ((x - b[i]) % b[length - 1] == 0 && (x - b[i]) / b[length - 1] >= 0) res++;
		} //特别的: &&之前是判断上述解题思路中有穷解的方法, 而其后则是保证二者符号相同
		  /* 
		  	例如该串最终1比0多两个, 则b[length - 1]为-2, 而此时我的(x-b[i])若等于2, 实际上是需要补1个
		  	0比1多2个的串, 进行判断这个串符不符合要求, 本身这个串是1比0多两个, 当然不符合要求, 
		  	但是2 % -2 和 2 % 2 结果都为0 因此他会认为这是符合条件的一种
		  */
		cout << res << endl;
	}
	return 0;
}

这次没啥可说的了, 都写在代码里了.

END

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值