题目链接:

https://codeforces.com/problemset/problem/1620/C

题目大意:

给定一个数 \(k\) 和一个由 'a' 和 * 构成的长为 \(n\) 的字符串,字符串中每一个 * 可以被 0 到 \(k\) 个 'b' 替换,要求输出第 \(x\) 小的字符串。

思路:

字符串从小到大的话,可以想到 从右往左 用 'b' 填充 *,这样子就可以实现从小到大去数第 \(x\) 个字符串。
将 'a' 隔开的 * 的字符串记录下来,从右往左标记为 \(s_1\)\(s_2\)\(s_3\)...,同时记每个字符串对应的长度为 \(cnt_1\)\(cnt_2\)\(cnt_3\)...,那么 \(s_1\) 包含了 \(cnt_1 * k + 1\) 种填充方式,即第 0 大到第 \(cnt_1 * k\) 小的字符串,所以开始的 \(x\)减 1。第 \(s_2\) 中每填一个 'b' 都会有 \(cnt_1 * k + 1\) 种方式
(因为它右边的 * 字符串有 \(cnt_1 * k + 1\) 种,以此类推,最后第 \(i\) 段字符串有 \((cnt_1 * k + 1) * (cnt_2 * k + 1) * ... * (cnt_{i - 1} * k + 1) * (cnt_i * k + 1)\) 种方案。)
\(i\) 段要放的 'b' 就是 \(x\) % \((cnt_i * k + 1)\) ,因为从右向左填充,所以每一段填充后,使 \(x\) 变为 \(x / (cnt * k + 1)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL T, n, k, x;
string s;
void solve(){
	cin >> n >> k >> x >> s;
	reverse(s.begin(), s.end());
	string ans = "";
	int cnt = 0;
	x--;
	for (int i = 0; i < n; i++){
		if (s[i] == 'a'){
			LL cur = cnt * k + 1;
			ans += string(x % cur, 'b') + 'a';
			x /= cur;
			cnt = 0;
		}
		else
			cnt++;
	}
	ans += string(x % (cnt * k + 1), 'b');
	reverse(ans.begin(), ans.end());
	cout << ans << "\n";
}
int main(){
	cin >> T;
	while(T--)
		solve();
	return 0;
}
posted on 2022-01-05 22:03  Hamine  阅读(134)  评论(0编辑  收藏  举报