[Luogu] P9687 题解
P9687 题解
看不懂题害死人,个人评价此题题意有些模糊。
题意:构造一个长度为 \(n\) 的 01 字符串 \(S\),此字符串有以下两点要求:
- 对于字符串中所有的 \(p\) 个不在字符串两端的 \(0\),它们左边和右边的一个字符为 \(1\)。
- 使构造出的字符串的字典序最小。
先设 \(S\) 完全由 \(0\) 构成。
对于点 1,设一变量 \(j\),为 \(S\) 中的字符序号。\(j\) 赋初始值为 \(1\)(因为“不在字符串两端”)。将 \(S\) 中的字符 \(S_j\) 左边和右边的元素改为 \(1\),(即 \(S_{j-1}\leftarrow 1,S_{j+1}\leftarrow 1\)),然后将 \(j\) 的值加上 \(2\),继续修改 \(S_{j+2}\) 左右两个元素,如此循环 \(p\) 次,此时所构造的 \(S\) 中,每两个 \(1\) 之间都由一个 \(0\) 隔开。
对于点 2,仅需倒序输出所构造的 \(S\) 即可。因为 \(S\) 是从开头开始构造的,所以 \(S_{0}\) 一定为 \(1\),若 \(p\) 远小于 \(n\),则 \(S\) 的后半段大部分都是 \(0\),此时倒序的字符串的字典序是小于原字符串的,而且符合以上两点要求。也就是说,倒序字符串的字典序小于等于原字符串,且符合要求,所以倒序输出即可。
那如何判断输出 \(-1\) 呢?若 \(2p\ge n\),则输出 \(-1\),否则输出所构造的 \(S\)。因为每两个 \(1\) 之间都由一个 \(0\) 隔开,所以从第一个 \(1\) 到最后一个 \(1\) 的长度就为 \(2p+1\),如果 \(2p\ge n\),则 \(2p+1\) 是一定大于 \(n\) 的,构造出的 \(S\) 长度须小于等于 \(n\) 才合法,所以此时就输出 \(-1\)。
#include <bits/stdc++.h>
using namespace std;
const int N = 114514;
int t, n, p;
int s[N];
int main() {
cin >> t;
while (t--) {
int j = 1;
cin >> n >> p;
if (2 * p >= n) {//判断是否输出 -1
cout << -1 << '\n';//记得换行!
continue;
}
else {
for (int i = 0; i < n; ++i) s[i] = 0;//将字符串中的元素都改为 0
for (int i = 0; i < p; ++i) {
s[j + 1] = 1;
s[j - 1] = 1;
j += 2;
}
for (int i = n - 1; i >= 0; --i) {
cout << s[i];//倒序输出
}
cout << '\n';//记得换行!
}
}
return 0;
}

浙公网安备 33010602011771号