P8437 伟大的神 题解
题目大意
给出 \(n\), \(m\), \(k\),求满足下面条件的字符串
- 只包含 l或r
- 总长是 \(n\)
- 最多有 \(k\) 个相同字符连在一起
- 最长的神之字符串长度为 \(m\)
上面对神之字符串的定义是:字母出现次数都相同的字符串
题解
Subtask 1
既然有 \(k=1\),那么就只有一种构造的方式,使相邻两位不相同。
于是代码就出来了。
const std::vector<std::string> s{"l", "r"}; // 保证这一行只出现这一次
if (k == 1) {
	for (int i = 0; i < n; i++) {
		std::cout << s[i & 1];
	}
	return 0;
}
Subtask 2
满足 \(n=m\) 的条件,显然整个字符串都是神之字符串,于是可以用和上面构造方式相同的方式构造。
if (n == m) {
	for (int i = 0; i < n; i++) {
		std::cout << s[i & 1];
	}
	return 0;
}
Subtask 3
有一个条件 \(k \geq 3\),显然对于这样的性质,我们可以先用 lrlr…… 的方式构造出前 \(m\) 个字符,满足神之字符串的条件,然后对于剩下 \(n - m\) 个字符,我们通过这样的重复构造就可以了 llrllrllr……。
if (k >= 3) {
	for (int i = 0; i < m; i++) {
		std::cout << s[i & 1];
	}
	std::string p = "lllr";
	for (int i = m; i < n; i++) {
		if (i + p.size() < n) {
			std::cout << p;
			i += p.size() - 1;
		} else {
			for (int j = 0; j < n - i; j++) {
				std::cout << p[j];
			}
			return 0;
		}
	}
}
Subtask 4
当 \(k = 2\) 时可以发现上面的那种构造方式是会被 hack 的,这里有一种 hack 的数据,我们研究一下
10 4 2
上面的代码会输出
lrlrllrllr
我们看这个子串
rlrllr
显然是神之字符串但是不符合题意的,粗暴地,我们删掉第一个 lr,在构造就可以发现:
lrllrllrll
满足了条件!
于是就可以这样的构造
for (int i = 0; i < m - 2; i++) {
	std::cout << s[i & 1];
}
std::string p = "llr";
for (int i = m - 2; i < n; i++) {
	if (i + p.size() < n) {
		std::cout << p;
		i += p.size() - 1;
	} else {
		for (int j = 0; j < n - i; j++) {
			std::cout << p[j];
		}
		return 0;
	}
}
完整代码
就不占篇幅了,这里 代码
 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号