蓝桥杯上Excel地址c语言,2017蓝桥杯Excel地址(C++C组)

题目:Excel地址

Excel单元格的地址表示很有趣,它使用字母来表示列号。

比如,

A表示第1列,

B表示第2列,

Z表示第26列,

AA表示第27列,

AB表示第28列,

BA表示第53列,

....

当然Excel的最大列号是有限度的,所以转换起来不难。

如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?

本题目既是要求对输入的数字, 输出其对应的Excel地址表示方式。

例如,

输入:

26

则程序应该输出:

Z

再例如,

输入:

2054

则程序应该输出:

BZZ

我们约定,输入的整数范围[1,2147483647]

资源约定:

峰值内存消耗(含虚拟机) < 256M

CPU消耗  < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

注意:

main函数需要返回0;

只使用ANSI C/ANSI C++ 标准;

不要调用依赖于编译环境或操作系统的特殊函数。

所有依赖的函数必须明确地在源文件中 #include

不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

------------------------------

笨笨有话说:

这有点像进制关系,又不完全是。好像末2位是以1当26,末3位是以1当26*26

歪歪有话说:

要是从字母序列转数字还好点,倒过来有点麻烦,不过计算机跑得快啊。

解析:

初读这道题,感觉挺简单的,不就是自定义一个进制系统么?后来才发现,我太低估这道题了。为什么说低估它了呢,听我细细到来.首先,按照我们传统的对二进制,八进制,十进制,十六进制数的传统思维做这道题,会陷入一个恶性循环的思维,这是这道题最大的难点,因为,你要注意到如果让你表示十进制的10和这道题的第27列,你怎么完成这个思维的过度呢,首先10是一个两位数,拆分为1和0,他们不一样,而用这道题的正确答案来表示27列是AA,拆分为A和A,他们一样,有人说,我用Z来表示在这道题中的进制系统中和十进制系统中10同样的地位(有人这听不懂了,这是一个思维过度,多看几遍,用笔划一下,就知道我说啥了),可是,10是双位数,Z是单位数. 以上的两种解法采取哪种合适呢,看题目,题目中说A表示1,AA表示27,并且有26个字母,恰好1 + 26 = 27,所以,我们果断选择第二种思维,同时也决定了,这道题采用的进制系统为26进制系统,但是我们在第二种方法还遗留了一个问题,更何况我们早已习惯二进制,八进制,十六进制,十进制系统中都有0的传统思维,这两个问题该怎么解决呢?一个办法,等效替代法,我们可以把Z看为进位的26(十进制系统中的10),并在主观上就认为Z是26进制系统中最小的两位数,Z就等效为A0即26 * 1 + 0 = 26,注意,这点尤为重要,而且必须理解,因为,该题没有给出表示第0列的标志,但是我们根深蒂固的思想导致很难处理没有0的其他进制系统的运算,所以,我们这里采用这样的做法这是这道题解的核心。下面给出数据对照表,方便大家更直观的理解本题的26进制系统:

9b9e3a5d42fe73a15742d77adb968681.png

源码:

#include

using namespace std;

#define SUB 50

int sign[SUB] = {0};

int get_digits(int data);

void init_data(int data);

void view(int data[]);

void jud(int data);

int info;

int main(int argc,char** argv){

while(1){

printf("

");

cin >> info;

init_data(info);

jud(info);

}

}

void jud(int data){

bool state = true;

for(int i = 0;i < get_digits(data);i++){

if(sign[i] == 0){

state = false;

}

}

if(state){

view(sign);

}else{

if(data == 26){

cout << "Z";

}else{

for(int i = get_digits(data) - 1;i >= 0;i--){

if(sign[i] == 0){

sign[i - 1] = sign[i - 1] - 1;

sign[i] = 26;

}

}

view(sign);

}

}

}

void init_data(int data){

int sub = 0;

int sub_temp = get_digits(data);

while(data){

sign[sub_temp - 1 - sub] = data % 26;

data = data / 26;

sub++;

}

}

int get_digits(int data){

int order = 1;

while(data / 26){

data = data / 26;

order++;

}

return order;

}

void view(int data[]){

for(int i = 0;i < get_digits(info);i++){

switch(data[i]){

case 1:

cout << "A";

break;

case 2:

cout << "B";

break;

case 3:

cout << "C";

break;

case 4:

cout << "D";

break;

case 5:

cout << "E";

break;

case 6:

cout << "F";

break;

case 7:

cout << "G";

break;

case 8:

cout << "H";

break;

case 9:

cout << "I";

break;

case 10:

cout << "J";

break;

case 11:

cout << "K";

break;

case 12:

cout << "L";

break;

case 13:

cout << "M";

break;

case 14:

cout << "N";

break;

case 15:

cout << "O";

break;

case 16:

cout << "P";

break;

case 17:

cout << "Q";

break;

case 18:

cout << "R";

break;

case 19:

cout << "S";

break;

case 20:

cout << "T";

break;

case 21:

cout << "U";

break;

case 22:

cout << "V";

break;

case 23:

cout << "W";

break;

case 24:

cout << "X";

break;

case 25:

cout << "Y";

break;

case 26:

cout << "Z";

break;

case 0:

cout << "Z";

default:

break;

}

}

}

48cd58f94ff3dd46f491d4fd0aefd81b.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值