欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CodeForces - 1B Spreadsheets(进制转化)

程序员文章站 2022-05-09 16:18:39
...

在流行的电子表格系统 (例如 Excel) 中,使用以下的列编号方式。第一列编号为 A,第二列 — 编号为 B,等等,直到第 26 列被标识为 Z。然后使用两个字母的编号:第 27 列编号为 AA,第 28 列 — AB,第 52 列被标识为 AZ。在 ZZ 之后,接着使用三位字母进行编号,依次类推。

各行被标识为以 1 开头的整数。单元格的名称由列和行的编号组成。例如,BC23 是位于第 55 列、第 23 行的单元格名称。

有时使用另一种编号方式:RXCY,其中 X 和 Y 是整数,分别表示列和行的编号。例如,R23C55 表示前述示例中的单元格。

您的任务是写一个程序,读取给定的单元格坐标序列,并将每个单元格的编号方式转换为另一种编号方式。

输入

输入的第一行包含了整数 n (1 ≤ n ≤ 105),表示测试所用的坐标数目。然后跟随 n 行,每行均包含坐标。所有的坐标都是正确的,且列 和/或 行的数字不超过 106 。

输出

写出 n 行,每行应包含一个使用另一种编号方式的单元格坐标。

示例

输入

2
R23C55
BC23

输出

BC23
R23C55

看题目,一共两种形式表示,之间互相转化。个人感觉第一种形式(没有R C 的那个)好转化,直接将其中的字母转化为整型数据就可以了。但是第二种形式还要考虑整除和不整除。对于大佬来说,肯定很简单,对于我这个弱菜,有点难。

#include<iostream>
#include<stdio.h>
#include<bits/stdc++.h>
#include<string>
#include<sstream>
#include<string.h>
const int maxn=1005;
typedef long long ll;
using namespace std;
char s[maxn];
int b[maxn];
bool check()
{
	if(s[0]=='R')
	{
		for(int i=1;i<strlen(s);i++)
		{
			if(!isalpha(s[i]))
				continue;
			if(s[i]=='C'&& !isalpha(s[i-1]) && !isalpha(s[i+1]))
				return true;
		}
		
	}
	
	return false;
}


int main()
{
	int t;
	cin>>t;

	while(t--)
	{
		memset(b,0,sizeof(b));
		bool flag=false;
		cin>>s;
		if(check())
		{
			string lie;
			int lie1;
			int hang1=0;   //后面的那个数 
			sscanf(s,"R%dC%d",&hang1,&lie1);
			int i=0;
			while(lie1>0)
			{
				if(lie1%26==0)
				{
					b[i++]=26;
					lie1--;
				}	
				else
				{
					b[i++]=lie1%26;
				}
				lie1/=26;
			}
			i--;
			for(;i>=0;i--)
				printf("%c",b[i]+64);
			cout<<hang1<<endl;	
			
		}
		
		
		else
		{
			int lie=0;
			int hang=0;
			int i=0;
			while(isalpha(s[i]))
			{
				lie=lie*26+(s[i]-'A'+1);
				i++;
			}
			while(!isalpha(s[i])&&i<strlen(s))
			{
				hang=hang*10+(s[i]-'0');
				i++;
			}
			cout<<'R'<<hang<<'C'<<lie<<endl;
		}
	}
	return 0;
}

第二种形式的话,就是一位一位的算每一个字符,比如Z是26,'Z'-'A'+1,  AZ 就是52,就是('A'-'A'+1)X 26+('Z'-'A'+1).然后你就找到规律了,isalpha( ),来判断是不是字母,就这样,然后就将其中的数字提取出来,就可以了。

                while(isalpha(s[i]))
			{
				lie=lie*26+(s[i]-'A'+1);
				i++;
			}

下面看看第一种形式的处理,就像第二种转换为第一种的样子一样,像一个 结果=乘数X商+余数(可能是0),这个余数就是字母转化而来的,从这个余数,我们就可以得到原先的字母。下面我说说(可能是瞎说的,因为喝了冰阔落(可乐)),就像上面第二种转化为第一种的一样,比如5678 这个数据怎么来的,5X10X10X10+6X10X10+7X10+8X1,所以往回倒退的时候,是从后面逐渐往回退的,所以第一种转化为第二种的话,需要我们做取余和除法的操作,思路应该是这样。(感觉我在说小学数学)。这个不是十进制,而是26进制,比如Z 是26,下一个就是AA 是27....AZ是52,BA是53,所以说到整除时(26,52,78...),还没有进到下一位的(对于我菜鸡,有的坑,脑子转的慢,哎),这时操作是,(  拿52来说,取余为0 (  最后一位是Z  )   ,52/26=2(  是个字母 B  ),这样算的话,是BZ,但是结果是AZ,就WA了。这时怎么办呢,只要遇见整除的,直接将这个被除数减一,毕竟大于等于26的数除以26都是大于0的,被除数减一,下一次的余数就会减一,就像52,商为2,减一,下次得到的字母就是A,这样就是正确答案了 AZ  );不整除的话,跟十进制操作一样,取余和除法。   我们将这些余数( Z 整除例子)都保存在一个数组中(整形,在后面转化为字符 %c ),Z例子就是保存 26,其他数据保存余数。因为是取余数除法操作(是反着来的),所以我们输出字母都是倒着输出。就这样说完了。

接下来,就是交代码,看到Accept(绿色),内心一喜。