2018年3月31日天梯赛L1-2
L1-2倒数第N个字符串
题目
给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, ..., aaz, aba, abb, ..., abz, ..., zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。
输入格式:
输入在一行中给出两个正整数 L(2 <= L <= 6)和 N(<= 105)。
输出格式:
在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。
输入样例:
3 7417
输出样例:
pat
解题思路:
相信很多人在做蓝桥杯模拟题时做过一个26进制的字母问题,大部分人将此题转化为类似于26进制的进制问题。这里我的思路代码比较复杂,时间复杂度比较高,但是比较好理解,而且也没有超时(要是超时了我也用进制的办法。。)
题目给出 l 个字符,那么也就确定了这个字符串的最大值是“zzzzz...”( l 个“z”),而且是求倒数第n个字符串,那么我们就逐个字符串减一(利用ASCII码值)。为了方便计算,我们把字符串倒过来,即ss[0]是字符串最右的字符。利用循环将最低位的字符减“1”,如果减完为“a”,那么就借位减一,变为“ ‘z’+1 ”,因为下一次循环要执行减“1”变为“z”,此处改变其实是提前了。对于借位没什么好说的,利用while循环,如果借位是“a”,那么就变为“z”继续借位,否则当前位减“1”就好了。
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int l,n;
cin>>l>>n;
char ss[6];
for(int i=0;i<l;i++){ //首先为字符串赋值,全为“z”
ss[i]='z';
}
if(n==1){ //倒数第一个肯定就是原字符串了,直接输出,不要进循环,方便下边计数
for(int i=l-1;i>=0;i--){
cout<<ss[i];
}
return 0;
}
int count=1; //因为上边已经判断过了,所以不可能出现倒数第一个字符串,所以从1开始计数
int ge=0; //这个ge其实代表个位的意思,即字符串的最低位
while(1){
count++;
ss[ge]--;
/*
for(int i=l-1;i>=0;i--){
printf("%c",ss[i]);
}cout<<endl<<endl;
*/
if(count==n){
break;
}
if(ss[ge]=='a'){
int now=ge+1;
while(1){
if(ss[now]=='a'){
ss[now]='z';
now++;
}else{
ss[now]--;
break;
}
}
ss[ge]='z'+1;
}
}
for(int i=l-1;i>=0;i--){
printf("%c",ss[i]);
}
return 0;
}