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;
}
posted @ 2018-04-02 10:57  Masart  阅读(176)  评论(0编辑  收藏  举报