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;
}