CF-Round#629-div3-B题

CF-Round#629-div3-B题

B. K-th Beautiful String

传送门

这道题的ac人数没有c题多呀~

这道题是模拟,思维,排列题

题目要求一个长度为n的序列需要有n-2个’a’,2个’b’。
给你一个n,和k(k代表字典序列排出来的第k个序列)
输出第k个序列
先开始。我以为是一个permutation题。然而。我发现不对劲。符合要求的序列只有n*(n-1)/2(题目中给了)
所以是到下标处理,思维题

其中有两个关键的式子:
n - i - 1和n - k
着重解释一下:
实例:aaabb(初始序列第一个)
我们把左边的b叫做leftb,右边的b叫做rightb;
我们考虑。leftb是从下标index = n-2开始向左移动的,这个时候rightb的可能位置有多少呢。比如上述序列rightb的可能位置只有一种可能。
如果是aab的话rightb的位置有两种可能。所以这个可能的数量是跟leftb和n有关的。
当前leftb索引index = i的话
那么rightb的可能位置有n - 1 - i种情况(这个地方简单)
然后考虑第k个序列
如果k > n - 1 - i的话。说明leftb不应该在当前这个位置。
比如上述情况aab
的话。(这个只能正好对应求k = 1和k = 2的情况)
所以k > n - 1 - i时我们需要把leftb往前移。
直到k <= n - 1 - i为止。
这种情况下,leftb已经到达应该到达的位置,我们现在求rightb的位置。
因为按照字典序嘛。自然是从后往前数啦~(字典序从小到大,b > a)
rightb的下标和k与n有关。因为从后往前。
所以自己简单举个例子就可以知道rightb的位置是 n - k;
比如求n = 5, k = 5的时候满足要求的序列是ababa
我们求得i = 1时满足要求(前面步骤省略了)。此时k = 2;n - i - 1 = 3;从右往左数的话就是下标为3的位置。正好是n - k

代码就很简单啦~
想清楚以后也很简单啦~

代码部分:

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n, k;
		cin >> n >> k;
		string s(n, 'a');
		for (int i = n - 2; i >= 0; i--)
		{
			if (k <= (n - i - 1))
			{
				s[i] = 'b';
				s[n - k] = 'b';
				break;
			}
			k -= (n - i - 1);
		}
		cout << s << endl;
	}
	return 0;
}
发布了127 篇原创文章 · 获赞 3 · 访问量 3227

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/105150229