CF1B-Spreadsheet题解

题目传送门

题意:在表格中格子有两种表示方式,一种为列从 A-Z,AA-ZZ,AAA-ZZZ...,行为 1,2,3...,如 B2BC23 等。另一种为 R+行+C+列 的形式,如 R23C45 等。你需要进行回答若干次询问,每次给出一个坐标,将其转换为另一种形式。

首先需要判断输入的是哪种形式,两种较为简洁的做法如下:

  1. 可以使用 sscanf 或 stringstream 来从字符串进行读入,判断是否能读入到 char+int+char+int 类型。
  2. 可以将字母和数字分段存入 vector,判断有几段。

处理主要涉及 10 进制和 26 进制的互相转换,这一步基本没有太大区别,可以循环也可以递归。

做法一 By ZhouYuChen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<cstdio>
void g(int t){if(t){g((t-1)/26);putchar(65+(t-1)%26);}}
int main(){
int n,x,y;
char s[64],*p;
for(scanf("%d ",&n);n--;){
gets(s);
if(sscanf(s,"%*c%d%*c%d",&x,&y)==2){
g(y);
printf("%d\n",x);
}else{
for(x=0,p=s;*p>64;++p)
x=x*26+*p-64;
printf("R%sC%d\n",p,x);
}
}
return 0;
}

做法二 By RAD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
char buf[110000];

inline int from(string &s) {
int res = 0;
forn(i, s.size())
res = res * 26 + s[i] - 'A' + 1;

return res;
}

inline void toRC(vector<string> &v) {
printf("R%dC%d\n", atoi(v[1].c_str()), from(v[0]));
}

void to(int x) {
int st = 1, len, sum = 0;
forn(i, 20) {
st *= 26;
sum += st;
if (x <= sum) {
len = i + 1;
break;
}
}

x -= sum - st + 1;
string res(len, 'A');
forn(i, len) {
res[len - i - 1] += x % 26;
x /= 26;
}

printf("%s", res.c_str());
}

inline void fromRC(vector<string> &v) {
to(atoi(v[3].c_str()));
printf("%s\n", v[1].c_str());
}

int main() {
int tt;
scanf("%d", &tt);
forn(ii, tt) {
scanf("%s", buf);
string s = buf;

vector<string> v;
forn(i, s.size()) {
int j = i;
string cur;
while (j < (int)s.size() && isalpha(s[j]) == isalpha(s[i])) {
cur += s[j];
j++;
}

i = j - 1;
v.pb(cur);
}

if ((int)v.size() == 2)
toRC(v);
else
fromRC(v);
}

return 0;
}