励志用更少的代码做更高效的表达
题目描述
Excel单元格的地址表示很有趣,它使用字母来表示列号。
比如,
A表示第1列,
B表示第2列,
Z表示第26列,
AA表示第27列,
AB表示第28列,
BA表示第53列,
…
当然Excel的最大列号是有限度的,所以转换起来不难。
如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?
本题目既是要求对输入的数字, 输出其对应的Excel地址表示方式。
例如,
输入:
26
则程序应该输出:
Z
再例如,
输入:
2054
则程序应该输出:
BZZ
我们约定,输入的整数范围[1,2147483647]
解题思路
Excel单元格… 算了。题意很简单,A-Z代表1-26, 如:BZZ = 2*26² + 26*26¹ + 26*26º = 2054
这种划分题无非两种分法:从大至小划分, 或从小至大取余划分。
受惯性思维影响, 最初的想法是从大至小划分,因为总觉得划分了大块在去划分小块要容易些(汗,和我一样想法的举个爪)。但在解释样例的时候, 我发现如果按照从大至小的思想来做, BZZ会被解释称C空Z, 因为第二个Z的26*26
可以看做1*26*26
, 即若某个字母为Z,它就可以被前一个字母表示。 遂放弃。
那就只剩从小到大取余划分了, 由于逻辑比较绕, 因此选择先在草纸上实现代码, 最后誊到编译器上。
总结:本题思路不难, 但由于走岔了路, 还是做了好久才搞出来。
代码展示
#include<bits/stdc++.h>using namespace std;int main() {//定义一个数组, 存储1-26 方便映射int a[26];a[0] = 26;for(int i = 1; i < 26; i++) a[i] = i; int n; cin>>n;string s;int num = 0;while(n>0) {int k1 = pow(26, num+1);//将其不能被k1整除的部分整合成字母。int k = n%k1;k /= pow(26, num);int x = a[k];s += (char)(x-1+65);n -= pow(26, num)*a[k];num++; }int len = s.length();for(int i = len-1; i >= 0; i--) cout << s[i];return 0; }