因爲喜歡,所以堅持
本來也是覺得腦子不清晰,但是不然,就是想不到!CF題目都對一些基本知識考查得十分滴靈活。。。。。
縷清思路:
題意先給個字符串s,裏面都是1或0,一個串的前綴,在題目中也給出了,字符串t的定義是無數個s拼接起來,現在給定n爲字符串s長度以及x讓求有多少個t的前綴滿足在前綴中0的個數-1的個數等於x,若前綴無限多個,那麼輸出-1
那麼思考一下,這樣的題目肯定得對x和序列中0的個數-1的個數進行判斷,分類要做好!但是也不能分太多,別把自己分迷了!跟沒說一樣。
利用前綴和記錄當前位置0的個數-1的個數爲多少,然後看代碼吧。主要代碼借鑑https://me.csdn.net/qq_43734635這位大佬
#include <cstdio>
#include <iostream>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <cmath>
using namespace std;
typedef long long LL;
int dis[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
const int maxn = 100000 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
char s[maxn];
int sum[maxn]; // 記錄當前位置0的個數-1的個數 是多少
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int T;
int n, x;
cin >> T;
while (T--)
{
cin >> n >> x;
int ans = 0;
if (x == 0)
ans++; // 如果爲 x 爲 0 那麼空串鐵定滿足
scanf("%s", s + 1); // 從下標1 開始放字符
for (int i = 1; i <= n; i++)
{
if (s[i] == '0')
sum[i] = sum[i - 1] + 1;
else
sum[i] = sum[i - 1] - 1;
}
int all = sum[n]; // 這一個週期的增量
if (all == 0)
{
if (x == 0) // 一個週期至少一個 無窮
printf("-1\n");
else
{
for (int i = 1; i <= n; i++)
{
if (sum[i] == x)
ans++;
}
if (ans)
printf("-1\n"); // 一個週期至少一個 無窮
else
printf("0\n"); // 每一個週期內都沒有
}
}
else
{
for (int i = 1; i <= n; i++)
{
if (((x - sum[i]) % all == 0) && (x - sum[i]) / all >= 0)
ans++;
// 爲什麼all!= 0 的時候只需要掃描一次序列就可以呢,因爲在同一個位置加上一個增量不會是同一個值了
// 理解爲某個位置的前綴和加上n個週期的貢獻爲x且貢獻次數即之前的週期次數大於等於0次
// 這樣就不用考慮正負號的問題了
}
printf("%d\n", ans);
}
}
return 0;
}