【刷题】【cf】B. Spreadsheets (1600)
题目大意:
不同的电子表格,有不同的方法表示一个元素(第x行第y列):
比如第23行第55列,可以表示为:R23C55、BC23
第二种表示方式前面的字母,按照A , B , ... , Z , AA , AB , ... , AZ , BA , ... , BZ , ... , ZZ , AAA , AAB , ... 的顺序排列。
你的任务是,给定一个元素的一种表示方式,用另一种表示方式,输出这个元素。
样例:
input:
2
R23C55
BC23
output:
BC23
R23C55
思路:
首先肯定是区分给的数据,使用的是哪种表示方式,(坑点1:R开头的不一定是第一种,也可能是R12这种数据)
对于输入的字符串,进行切割,找出每一块的数据,然后该转化为数字就转化,该改成字符串就改成字符串。
这里的第二种方法的前缀,乍一看很像是26进制,但是计算发现实际上有所不同:
A - 1 (第一点,转化成的数字,是从1开始而不是从0开始)
Z - 26
AA - 27 (按照进制,A-Z表示0-25,那么AZ - 0 25 与 Z - 25 一样,实际并非如此)
所以与进制并不像,不能瞎搞了。
那么抛开进制变形,不如直接找规律
发现 x % 26 - 1 就是末尾的数字 (坑点2 :不能 'A' + x%26 - 1这么输出,会出现@符号,要改成(x+25)%26 )
然后 x/=26 就可以继续这个操作
发现实际上这个算法拟合还是有问题,所以修正一下
原来
while(y>0 ) { sta.push('A'+(y+25)%26 ); y/=26; }
改后
while(y>0 ) { y--; sta.push('A'+y%26); y/=26; }
然后就过了某些wa的点
完整代码
#include<bits/stdc++.h> using namespace std; int T; string s; stack <char > sta ; long long x,y; int i; bool is_number(char ch) { if(ch<'0' ) return false; if(ch>'9' ) return false; return true; } bool find() { if(!is_number(s[1]) ) return false; int pos=2; while(is_number(s[pos]) ) pos++; if(s[pos]=='C' ) return true; return false;//结果这句话没写 } int main() { cin>>T; while(T--) { cin>>s;//为什么这里不用getchar if(s[0]=='R' && find() ) //R可能会用来计数,所以有wa的点 { i=1; x=0,y=0; while(is_number(s[i]) ) x=x*10+(s[i]-'0'),i++; i++; while(is_number(s[i]) ) y=y*10+(s[i]-'0'),i++; while(!sta.empty() ) sta.pop(); while(y>0 ) { //sta.push('A'+(y%26)-1 ); //注意这里写的简单,但是y%26=0时会爆炸 // sta.push('A'+(y+25)%26 ); y--; sta.push('A'+y%26); y/=26; } while(!sta.empty() ) { putchar(sta.top() ); sta.pop(); } printf("%lld\n",x); } else { i=0,x=0,y=0; while(!is_number(s[i]) ) i++; for(int j=0;j<i;j++) { y=y*26+(s[j]-'A')+1; } while(is_number(s[i]) ) x=x*10+(s[i]-'0'),i++; printf("R%lldC%lld\n",x,y); } } return 0; }