CF题目:C. K-th Beautiful String(找规律、暴力)
题目链接:https://codeforces.ml/problemset/problem/1328/B
题目概述:题目要求输出按照逆字典序排布的字符串,第一行数字n代表测试数据,以下n行每行两个数据n,m数据, n代表输出字符串长度,m代表字符串所处顺序
思路:我们可以将m看作移动两个b的次数,可以发现字符串中只有两个b,最初位于字符串中n-1、n的位置,每当第一个b向前移动时,第二个b就可以移动的次数比上次多一,第一个b最多向前移动n-2个位置,根据循环,当m>=第一个b
移动次数的阶乘时,此时了第一个b的位置,再根据m,从而就可以确定了第二个b的位置,跳出循环,输出字符串。
(第一遍直接暴力模拟,测试4时间超时(TLE))
TLE代码:
#include <iostream>
#include <string>
using namespace std;
int main(){
int N;
cin >> N;
while (N--) {
long long n, m;
cin >> n >> m;
string s(n, 'a');
m--; //因为当b=1,不用进入循环导致b1,b2变化,直接输出
long long b1 = n - 1, b2 = n;//b1代表第一个b的位置,b2代表第二个b的位置
while (m) {
m--;
if (b1 + 1 == b2) { //首先判断b1,b2是否相邻,若相邻,则前移b1,重置b2
b1--;
b2 = n;
continue;
}
b2--; //若b1,b2不相邻,则前移b1
}
s[b1 - 1] = 'b';//改变b1,b2的字符
s[b2 - 1] = 'b';
cout << s <<endl;
}
return 0;
}
AC代码:
#include <iostream>
#include <string>
using namespace std;
int main(){
int N;
cin >> N;
while (N--) {
long long n, m, sum=0;
cin >> n >> m;
long long b1 = n - 1, b2 = n; //初始化第一、二个b的位置
string s(n, 'a');
for (long long i = 1; i < n; i++) { //最多将第一个b前移n-1次
sum += i; //求每次前移第一个b时,所需的次数和,移动的次数即字符串逆字典序位置
if (sum >= m && (sum - i) < m) {//查找b1的位置
s[n - i - 1] = 'b'; //插入两个b
s[n - m + sum - i] = 'b';
break;
}
}
cout << s <<endl;
}
return 0;
}
如果有什么不懂、疑问、错误,欢迎指点,谢谢~