読者です 読者をやめる 読者になる 読者になる

Codeforces Beta Round #1 B. Spreadsheets

問題ページ

Problem - B - Codeforces

問題文

 人気な表計算システム(例えばExcelとか)では、列の表現方法として、以下に述べる方法が使われています。

  • 1列目はAという番号を持っています。2列目はB,3列目はC,...,26列目はZという番号を持っています。
  • それ以降は二つの文字を使います。27列目はAA,28列目はAB,...,52列目はAZです。
  • ZZの後には同じように3文字を使って表します。

 行は1から始まる整数によって番号付けされています。セルの名前はセルの列と行の連なりです。例えば、BC23は、55列目23行目のセルの名前です。

 時々、もうひとつ別の表現方法が用いられることがあります。その表現方法は、RXCY(XとYは整数で、それぞれ列と行番号を意味する) です。たとえば、R23C55は先ほどの例のセルを指します。

 あなたの仕事は与えられた一連のセルの座標を読み込み、それぞれの座標について別の表現方法に従って出力することです。

制約

  • 1≦n≦10^5(nは整数)
  • 列番号も行番号も10^6を超えないデータしか与えられない。
  • 正しい番号が与えられることが保障されている。

解法

反転↓

頑張って文字列の基数変換する。微妙に値弄ってやる(1足しながら10進数にしたり1引きながら戻したり)と辻褄があってうれしい。ソースは冗長。

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <sstream>
using namespace std;
#define INF (1<<29)
typedef unsigned int uint;

int isAnother(string s){
    if(s[0] != 'R') return false;
    if( !('0' <= s[1] && s[1] <= '9') )return false;
    if(s.find("C") == -1) return false;
    return true;
}
string toString(int n){
    n--;
    if(n == -1) return "";
    return toString(n/26) + string( 1 , 'A' + n % 26);
    
}

int toInt(string s){
    int ans = 0;
    for(int i = 0 ; i < s.size() ; i++)
        ans = ans * 26 + (s[i] - 'A') + 1;
    return ans;
}
int main(){
    int n;
    cin >> n;
    while(n--){
        string s; cin >> s;
        if(isAnother(s)){
            for(int i = 0 ; i < s.size() ; i++)
                if( !('0' <= s[i] && s[i] <= '9') ) s[i] = ' ';
            stringstream ss(s);
            int a,b;
            ss >> a >> b;
            cout << toString(b) << a << endl; 
        }else{
            int p = s.find_first_of("0123456789");
            int a = toInt(s.substr(0,p));
            int b = atoi(s.substr(p).c_str());
            cout << "R" << b << "C" << a << endl;
        }
    }
}