题目:
资源限制
内存限制:512.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
思路:
在小编看见这个题的时候一下子就想到了用输出流控制符来解决,就像这样:
cin >>hex >> num;
cout << oct << num <<endl;
很显然是小编轻敌了,这题远没有想象的那么简单,再看题干“每个十六进制数长度不超过100000”,这句话非常重要,题干的意思是输入的十六进制字符有十万位,这显然是一个非常大的数,利用输出流控制符的话1s的运行时间一定是不够的,所以我们先将16进制转换成2进制然后再对二进制分为3位一组进行转换。
算法实现:
首先我们可以把数字输入改写成字符串输入这样可以利用switch语句进行转换就像这样:
string trans_bin(string s)
{
string s_bin = "";
for (int i = 0; i < s.length(); ++i)
{
switch (s[i])
{
case '0': s_bin += "0000"; break;
case '1': s_bin += "0001"; break;
case '2': s_bin += "0010"; break;
case '3': s_bin += "0011"; break;
case '4': s_bin += "0100"; break;
case '5': s_bin += "0101"; break;
case '6': s_bin += "0110"; break;
case '7': s_bin += "0111"; break;
case '8': s_bin += "1000"; break;
case '9': s_bin += "1001"; break;
case 'A': s_bin += "1010"; break;
case 'B': s_bin += "1011"; break;
case 'C': s_bin += "1100"; break;
case 'D': s_bin += "1101"; break;
case 'E': s_bin += "1110"; break;
case 'F': s_bin += "1111"; break;
}
}
return s_bin;
}
这样我们就把十六进制转换成了二进制了,然后我们利用三个字符一组将二进制转换成八进制,
这里我们用到了substr(a,b )函数,这个函数可以用来截取从a开始到后面b位的字符。
代码如下
for (int i = 0; i < s.length(); i += 3)
{
if (s4.substr(i, 3) == "000")s1 += "0";
else if (s4.substr(i, 3) == "001")s1 += "1";
else if (s4.substr(i, 3) == "010")s1 += "2";
else if (s4.substr(i, 3) == "011")s1 += "3";
else if (s4.substr(i, 3) == "100")s1 += "4";
else if (s4.substr(i, 3) == "101")s1 += "5";
else if (s4.substr(i, 3) == "110")s1 += "6";
else if (s4.substr(i, 3) == "111")s1 += "7";
}
但是我们要知道这二进制字符不一定是三的整数倍,所以我们需要对数组进行倒叙并且再空位补上0然后在恢复原有顺序,具体代码如下:
string trans_oct(string s)
{
string print_s = "", re_s = "", s_temp = "";
for (int j = s.length() - 1; j >= 0; j--)
{
re_s += s[j];
}
if (re_s.length() % 3 != 0)
{
for (int i = 0; i < (3 - s.length() % 3); i++)
{
re_s += "0";
}
}
for (int j = re_s.length() - 1; j >= 0; j--)
{
s_temp += re_s[j];
}
for (int i = 0; i < re_s.length(); i += 3)
{
if (s_temp.substr(i, 3) == "000")print_s += "0";
else if (s_temp.substr(i, 3) == "001")print_s += "1";
else if (s_temp.substr(i, 3) == "010")print_s += "2";
else if (s_temp.substr(i, 3) == "011")print_s += "3";
else if (s_temp.substr(i, 3) == "100")print_s += "4";
else if (s_temp.substr(i, 3) == "101")print_s += "5";
else if (s_temp.substr(i, 3) == "110")print_s += "6";
else if (s_temp.substr(i, 3) == "111")print_s += "7";
}
if (print_s.substr(0, 1) == "0")
print_s = print_s.substr(1, print_s.length() - 1);
return print_s;
}
以上就是该算法的核心部分,接下来只需要按照输入输出要求完成剩余代码即可。
完整代码:
#include<iostream>
#include<string>
using namespace std;
string trans_bin(string s)
{
string s_bin = "";
for (int i = 0; i < s.length(); ++i)
{
switch (s[i])
{
case '0': s_bin += "0000"; break;
case '1': s_bin += "0001"; break;
case '2': s_bin += "0010"; break;
case '3': s_bin += "0011"; break;
case '4': s_bin += "0100"; break;
case '5': s_bin += "0101"; break;
case '6': s_bin += "0110"; break;
case '7': s_bin += "0111"; break;
case '8': s_bin += "1000"; break;
case '9': s_bin += "1001"; break;
case 'A': s_bin += "1010"; break;
case 'B': s_bin += "1011"; break;
case 'C': s_bin += "1100"; break;
case 'D': s_bin += "1101"; break;
case 'E': s_bin += "1110"; break;
case 'F': s_bin += "1111"; break;
}
}
return s_bin;
}
string trans_oct(string s)
{
string s_oct = "", re_s = "", s_temp = "";
for (int j = s.length() - 1; j >= 0; j--)
{
re_s += s[j];
}
if (re_s.length() % 3 != 0)
{
for (int i = 0; i < (3 - s.length() % 3); i++)
{
re_s += "0";
}
}
for (int j = re_s.length() - 1; j >= 0; j--)
{
s_temp += re_s[j];
}
for (int i = 0; i < re_s.length(); i += 3)
{
if (s_temp.substr(i, 3) == "000")s_oct += "0";
else if (s_temp.substr(i, 3) == "001")s_oct += "1";
else if (s_temp.substr(i, 3) == "010")s_oct += "2";
else if (s_temp.substr(i, 3) == "011")s_oct += "3";
else if (s_temp.substr(i, 3) == "100")s_oct += "4";
else if (s_temp.substr(i, 3) == "101")s_oct += "5";
else if (s_temp.substr(i, 3) == "110")s_oct += "6";
else if (s_temp.substr(i, 3) == "111")s_oct += "7";
}
if (s_oct.substr(0, 1) == "0")
s_oct = s_oct.substr(1, s_oct.length() - 1);
return s_oct;
}
int main()
{
int n;
cin >> n;
string s[10];
string bin, oct;
for (int i = 0; i < n; ++i)
{
cin >> s[i];
}
for (int i = 0; i < n; ++i)
{
bin = trans_bin(s[i]);
oct = trans_oct(bin);
cout << oct << endl;
}
return 0;
}
总结:
这道题其实也没有想象中那么复杂,核心部分就是利用分组转换的思想,所以阅读题干给的提示同样重要,同时不要局限于数字方面来思考,转换成字符类型有时候会有更简单的方法!!!!!