[Luogu] P9687 题解

P9687 题解

看不懂题害死人,个人评价此题题意有些模糊。

题意:构造一个长度为 \(n\) 的 01 字符串 \(S\),此字符串有以下两点要求:

  1. 对于字符串中所有的 \(p\)不在字符串两端\(0\),它们左边和右边的一个字符为 \(1\)
  2. 使构造出的字符串的字典序最小。

先设 \(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;
}
posted @ 2023-11-17 20:47  FurippuWRY  阅读(48)  评论(0)    收藏  举报