题目连接: 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;
}
这次没啥可说的了, 都写在代码里了.