传送门:http://lx.lanqiao.cn/problem.page?gpid=T51
题目:给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
解决方法:题目的提示其实很有道理,十六转八要怎么转换?中间使用什么进制来转换呢?
首先肯定想到的是10,但是十进制不合适,为何呢?
(其实是因为这个题目是个高大数据量的题目,其测试样例中有特别大的数以至于没有可以用的变量来承载它)
所以要考虑将16进制转为二进制,然后由二进制转为8进制
实际转换一下,会发现一个规律,就是三位十六进制数刚好转换为4位8进制数,原理:
一个十六进制数可以用四位二进制数表示,而一个八进制数可以用三个二进制数表示,所以三个十六进制数可以由四个八进制数表示。
那么问题就很好解决了,将十六进制字符串按三个分,转化为一个八进制串拼接即可。
答案:
#include<bits/stdc++.h>
using namespace std;
char str_16[100007];
int str_8[1000007];
void trans16to8(char *p,int *s){
int num = 0;
for(int i = 0;i < 3;i++){
if(p[i] >= 'A'){
num += (p[i] - 'A' + 10) * pow(16,2 - i);
}
else{
num += (p[i] - '0') * pow(16,2 - i);
}
}
for(int i = 0;i < 4;i++){
s[i] = num % 8;
num /= 8;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(str_8,0,sizeof(str_8));
str_16[0] = '0';
str_16[1] = '0';
scanf("%s",str_16+2);
int len = strlen(str_16 + 2);
int index = 0;
for(int i = len + 1;i >= 2;i--){
i--;
i--;
trans16to8(str_16 + i,str_8 + index * 4);
index++;
}
int flag = 1;
for(int i = index * 4 - 1;i >= 0;i--){
if(flag && str_8[i] == 0);
else {
flag = 0;
printf("%d",str_8[i]);
}
}
if(flag) printf("0");
printf("\n");
}
return 0;
}