题目链接:http://codeforces.com/contest/1/problem/B
题目大意:
《电子表格》
电子表格的第1列标记为A,第2列标记为B,……,第26列标记为Z。
然后我们用两个字符来进行:第27列标记为AA,第28列标记为AB,……,第52列标记为AZ。
……
在ZZ之后,我们再使用三个字符来表示。如是循环……
所以对于电子表格中的某一个元素,我们都可以按照上述方法标识它的列。
比如,对于第55列第23行的元素,我们可以用“BC23”来表示它。我们称这是“第一种表示”。
除了“第一种表示”外,还有“第二种表示”。
第二种表示的形式为“RXCY”,其中 X 和 Y 都是数字, X 表示行号, Y 表示列号。
比如,对于第55列第23行的元素,它的“第二种表示”为“R23C55”。
现在,给你 n 个字符串,对于每一个字符串,他可能是某一行某一列的“第一种表示”或“第二种表示”。
如果这个字符串是“第一种表示”,你需要将其转换为“第二种表示”;
否则,这个字符串就是“第二种表示”,你需要将其转换为“第一种表示”。
题目分析:
这个题目比较麻烦的地方在于它的进制转换上!
一位字符的范围在 [A, Z] 共 26 个数;
二位字符的范围在 [AA, ZZ] 共 26 x 26 个数;
三位字符的范围 [AAA, ZZZ] 共 26 x 26 x 26 个数;
以此类推, n 位字符的范围包含有 26^n 个数。
可以看出,对于具有固定位数 n 的字符对应的数,它其实就对应一个 n 位的26进制数。
所以,告知我们一个数 X ,我们确定它位数的方法为:
首先 n = 1;
比较 X 和 26 的大小,如果 X <= 26 ,返回 n; 否则,X -= 26 + 1, n = 2;(注意这里的 + 1 ,因为 Z + 1 才会变成 AA)
比较 X 和 26^2 的大小,如果 X <= 26*26,返回 n;否则,X-= 26*26 + 1, n = 3;
……
最终会:比较 X 和 26^n 的大小,找到 X <= 26^n,返回 n。
得到位数 n 以及此时的 X ,我们就可以根据剩下的 X 的值,来计算对应的字符了。
将数字转成字符表示的函数如下所示:
其次,我们考虑将一个字符串转成对应的数字,我们可以按照上述思想逆推回来进行思考:
对于一个长度为 n 的字符串 s ,它一定是经历了
26 (一位字符串)、
26^2 (二位字符串)、
26^3 (三位字符串)、
……
26^(n-1) (n-1位字符串)
的经历。
然后剩下的就是将这个 n 为字符串看做一个 26 进制数得到剩下的部分的数。实现代码函数如下:
最后整合一下上面两个代码。
另外一方面就是如何判断输入的字符串是“第一种表示”或“第二种表示”。不过这个不是问题,最难的问题已经在上面讲解完了。
这里需要特别注意的一点是,'A'并不代表0,而是代表1,所以在处理的时候,我们的转换逻辑是从0开始,但是处理逻辑却是从1开始,所以要处理好1这个数的差的细节。
实现代码如下:
#include <bits/stdc++.h> using namespace std; string change_d_to_s(int x) { x -= 1; int tmp_arr[10], n = 1, t = 26; while (x > t) { x -= t; t *= 26; n ++; } for (int i = 0; i < n; i ++) { tmp_arr[i] = x % 26; x /= 26; } string s = ""; for (int i = n-1; i >= 0; i --) { char c = 'A' + tmp_arr[i]; s += c; } return s; } int change_s_to_d(string s) { int n = s.length(); if (n == 1) { return s[0] - 'A' + 1; } int t = 1, ans = 1; for (int i = 1; i < n; i ++) { t *= 26; ans += t; } t = 1; for (int i = n-1; i >= 0; i --) { int tmp = s[i] - 'A'; ans += tmp * t; t *= 26; } return ans; } int n, x, r; string s; int main() { cin >> n; while (n --) { cin >> s; if (s[0] == 'R' && s[1] >= '0' && s[1] <= '9' && s.find('C') != string::npos) { // 第一种表示 istringstream sstream(s); char ch_R, ch_C; sstream >> ch_R >> r >> ch_C >> x; cout << change_d_to_s(x) << r << endl; } else { // 第二种表示 int i; for (i = 0; s[i] >= 'A' && s[i] <= 'Z'; i ++); istringstream sstream1(s.substr(0, i)); string t; sstream1 >> t; istringstream sstream2(s.substr(i)); sstream2 >> r; cout << "R" << r << "C" << change_s_to_d(t) << endl; } } return 0; }