Juju and Binary String
[Link](Problem - F - Codeforces)
题意
给你一个 01 01 01串 s t r str str长度为 n n n,这个串的权定为 o n e s n ( o n e s 为 1 的 数 量 ) \frac{ones}{n}(ones为1的数量) nones(ones为1的数量)。现在需要让你选择若干不相交的子串使得满足所有子串的长度和为 m m m且将子串拼接起来后的串 t t t的权和原串相同,问你最少需要多少个子串。
思路
首先 t t t中的 1 1 1的数量应该为 o n e s n m \frac{ones}{n}m nonesm,因为有整数个 1 1 1所以要满足 o n e s × m ≡ 0 ( m o d n ) ones\times m\equiv 0 (mod\ n) ones×m≡0(mod n),否则无解。
我们设 x = t 中 1 的 数 量 x=t中1的数量 x=t中1的数量,我们假设 s t r str str是一个环,如果一个连续长度为 m m m的子数组有 x x x个 1 1 1那么我们的答案就是 1 1 1或 2 2 2,不跨环即 1 1 1,跨环就是 2 2 2。
设 c i c_i ci为 s t r [ i . . . i + m − 1 ] i f i ≤ n − m + 1 e l s e s t r [ 1... m − ( n − i + 1 ) ] + s [ i . . . n ] str[i...i+m-1]\ if\ \ i\le n - m + 1\ else\ \ str[1...m-(n-i+1)]+s[i...n] str[i...i+m−1] if i≤n−m+1 else str[1...m−(n−i+1)]+s[i...n] 中 1 1 1的数量,则有 ∣ c i + 1 − c i ∣ ≤ 1 \vert c_{i+1}-c_i\vert \le 1 ∣ci+1−ci∣≤1,因为 c i + 1 c_{i+1} ci+1和 c i c_i ci最多只有两位不同当且仅当这两位不同的时候 ∣ c i + 1 − c i ∣ = 1 \vert c_{i+1}-c_i\vert =1 ∣ci+1−ci∣=1。因此 c i → c i + 1 c_i\to c_{i+1} ci→ci+1的变化是不跳跃的即连续的。
证 m a x ( c i ) ≥ x max(c_i)\ge x max(ci)≥x:设 m a x ( c i ) < x max(c_i)<x max(ci)<x,则 ∑ i = 1 n c i < n x \sum_{i=1}^n c_i < nx ∑i=1nci<nx, ∑ i = 1 n c i = m × o n e s ( 每 个 1 会 出 现 m 次 ) \sum_{i=1}^n c_i=m\times ones(每个1会出现m次) ∑i=1nci=m×ones(每个1会出现m次),即 m × o n e s < n x → x > o n e s n m m\times ones<nx\to x>\frac{ones}{n}m m×ones<nx→x>nonesm,与 x x x的定义不同即不成立,所以 m a x ( c i ) ≥ x max(c_i)\ge x max(ci)≥x。
证 m i n ( c i ) ≤ x min(c_i)\le x min(ci)≤x:设 m i n ( c i ) > x min(c_i)>x min(ci)>x,则 ∑ i = 1 n c i > x → m × o n e s > n x → x < o n e s n m \sum_{i=1}^{n}c_i>x\to m\times ones >nx \to x<\frac{ones}{n}m ∑i=1nci>x→m×ones>nx→x<nonesm,与 x x x的定义不同不成立,所以 m i n ( c i ) ≤ x min(c_i)\le x min(ci)≤x。
所以 m i n ( c i ) ≤ x ≤ m a x ( c i ) min(c_i)\le x \le max(c_i) min(ci)≤x≤max(ci),并且 c i c_i ci是连续的,所以 必定存在一个 c j = = x c_j==x cj==x,因此答案不是 1 1 1就是 2 2 2。
前缀和处理一下,对于大于等于 m m m的每个点判断一下是否成立即可。
Code
#include <bits/stdc++.h>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[N];
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int T;
cin >> T;
while (T -- ) {
cin >> n >> m;
string str; cin >> str;
int ones = 0;
for (auto x : str)
if (x == '1') ones ++;
if ((LL)ones * m % n) {
cout << "-1\n";
continue ;
}
ones = (LL)ones * m / n;
vector<int> s(n * 2 + 1);
for (int i = 1; i <= n * 2; i ++) {
s[i] = s[i - 1] + (str[(i - 1) % n] == '1');
if (i >= m && s[i] - s[i - m] == ones) {
if (i <= n) {
cout << 1 << '\n';
cout << i - m + 1 << ' ' << i << '\n';
break;
}
else {
cout << 2 << '\n';
cout << 1 << ' ' << i - n << '\n';
cout << n - (m - i + n) + 1 << ' ' << n << '\n';
break;
}
}
}
}
return 0;
}
本文解析了Codeforces F题的解决思路,通过环状数组处理和前缀和优化,找到符合条件的子串,实现字符串权值匹配。
304

被折叠的 条评论
为什么被折叠?



