Educational Codeforces Round 81 (Rated for Div. 2)B. Infinite Prefixes(思维、公式推导)

题目地址:https://codeforces.com/contest/1295/problem/B
参考大佬的地址:https://www.cnblogs.com/pixel-Teee/p/12247178.html

题意:
	每组输入一个n和m,n代表字符串s的长度,m的意思是01的数量多m个
	你有一个字符串s,字符串s是一个01串,字符串t是由无限个字符串s相连,例如s="01001"那t可以等于"0100101001......"。
	题目给出一个s,问:在t中有多少个位置是  0的数量 - 1的数量 = m  。

解决方法:
	使用前缀和记录一个s内,每个s[i]的值。
		例如:s = "01001"
		则前缀和数组sum = {0,1,0,1,2,1}
	记录后,有两种情况:
		1.sum[n] = 0;	此时字符串s中01的数量相同
			a.此时如果数组内  没有任何一个数=m的时候  ,即使再增加无数个s,也不会存在sum[i] = m的情况。所以可以输出0
				例如:s="0101",m = 2;
				此时前缀和数组为{0,1,0,1,0},并且每增加一个s就会多出一组{1,0,1,0}所以永远也不会出现sum[i] = 2的情况。

			b.此时如果数组内  有z个数=m(z>0)  ,那每增加一个s,就会多出z个数=m,而s可以无限次叠加,所以数量无法计算,输出-1。
				例如:s = "0101",m = 1;此时前缀和数组为{0,1,0,1,0},并且每增加一个s就会多出一组{1,0,1,0},所以会出现无数种sum[i] = 1的情况。
		
		2.sum[n] != 0;	此时字符串s中01的数量不同,则01的数量会随着字符串的不断叠加而递增或者递减。
		以样例解释:
		6 10
		010010
		n = 6, m = 10;
		t = s时: t = "0,1,0,0,1,0";
		sum = {0,   1,0,1,2,1,2};
		当sum[i] + k * sum[n] = x的时候,那这个位置就是符合的。
		x和sum[i]和sum[n]都是已知的,所以可以通过移项变成x - sum[i] = k * sum[n];
		(x - sum[i]) / sum[n] = k;
		(x - sum[i]) % sum[n] = 0;
		所以当(x - sum[i]) % sum[n]  = 0(x - sum[i]) / sum[n] > 0的时候,就可以让结果+1.
		注意:在判断的时候将sum[0]除去,因为它时为了方便创造前缀和数组的,它并不是前缀和数组里面的一个成员。而且当m=0的时候,空串也算一个结果,需要特殊判断一下。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define dd double
#define PI acos(-1.0)
#define f(i, x, y) for(ll i = x; i < y; i++)
using namespace std;
const ll MAXN = 2e5 + 5;

ll sum[100005];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	ll t; cin >> t;
	while (t--) {
		ll n, m; cin >> n >> m;
		string s; cin >> s;
		sum[0] = 0;
		f(i, 1, n + 1) {
			if (s[i - 1] == '0') {
				sum[i] = sum[i - 1] + 1;
			}
			else {
				sum[i] = sum[i - 1] - 1;
			}
		}
		ll ans = 0;
		if (sum[n] == 0) {
			bool flag = true;
			f(i, 0, n + 1) {
				if (sum[i] == m) {
					flag = false;
					cout << "-1" << endl;
					break;
				}
			}
			if (flag) {
				cout << "0" << endl;
			}
		}
		else {
			if (m == 0) {
				ans++;
			}
			f(i, 1, n + 1) {//不算前缀和数组的第一个sum[0]
				if ((m - sum[i]) % sum[n] == 0 && (m - sum[i]) / sum[n] >= 0) {
					ans++;
				}
			}
			cout << ans << endl;
		}
	}
}

你可能感兴趣的:(公式推导,codeforces,c++)