这个题还是有点含金量,第一遍做出来,很可能会超时,比如以下代码:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int times = sc.nextInt();
for (int i=0;i<times;i++){
long Ten = 0;
String str = sc.next();
Ten = SixToTen(str);
TenToEight(Ten);
}
}
public static long SixToTen(String str){
long result = 0;
char[] ch = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (int i=0;i<str.length();i++){
long t=1;
for (int j=0;j<ch.length;j++){
if (str.charAt(i) == ch[j]){
for (int m=0;m<str.length()-i-1;m++){
t = 16*t;
}
t = j*t;
}
}
result = result+t;
}
return result;
}
public static void TenToEight(long i){
boolean t = true;
ArrayList<Long> result = new ArrayList<Long>();
if (i == 0){
result.add((long)0);
}else{
while(t){
if (i==0){
break;
}else{
result.add(i%8);
i = i/8;
}
}
}
for (int n=result.size()-1;n>=0;n--){
System.out.print(result.get(n));
}
System.out.println();
}
}
在这我用的是十六进制转十进制再转八进制,在十六转十的过程中,用到了三层循环,复杂度比较高,所以非常非常非常容易超时,再加上用的是long类型,还会涉及到位数不够的情况。
这段代码测试了两次,均提示我说运行超时,当我把蓝桥的测试数据打开的时候,被吓到了……如下:
input:
10
76
931FA
C9DAB2B36C
248B87D6AE33F9A
62D7183A5D5789E4B2D6
B441E2411DC709E111C7E1E7ACB6F8CAC0BB2FC4C8BC2AE3BAAAB9165CC458E199CB89F51B135F7091A5ABB0874DF3E8CB45
43A5EB93B0441E9CA4C2B0FB3D30875CBF29ABD5B1ACF38984B35AE882809DD4CFE7ABC5C61BAA52E053B4C3643F204EF259D2E98042A948AAC5E884CB3EC7DB925643FD34FDD467E2CCA406035CB2744CB90A63E51C9737903343947E02086541E4C48A99630AA9AECE153843A4B190274EBC955F8592E30A2205A485846248987550AAF2094EC59E7931DC650C7451CC61C0CB2C46A1B3F2C349FAFF763C7F8D14DDFF946351744378D62C59285A8D7915614F5A2AC9E0D68ACA6248A9227AB8F1930EE38AC7A9D239C9B026A481E49D53161F9A9513FE5271C32E9C21D156EB9F1BEA57F6AE4F1B1DE3B7FD9CEE2D9CCA7B4C242D26C31D000B7F90B7FE48A131C7DEBFBE58165266DE56E1EDF26939AF07EC69AB1B17D8DB62143F2228B51551C3D2C7DE3F5072BD4D18C3AEB64CB9E8CBA838667B6ED2B2FCAB04ABAE8676E318B402A7D15B30D2D7DDB78650CC6AF82BC3D7AA805B02DD9AA523B7374A1323EE6B516D1B81E5F709C2C790EDAF1C3FA9B0A1DBC6DABC2B5ED267244C458752002B106D6381FAD58A7E193657BDE0FE029120F8379316891F828B8D24A049E5B86D855BCFED56765F9DA1AC54CAEAF9257ABC67B451BC70B0E52817DD1B704A6B418A83FD4A9CA4C89E1A6E779F8D9E9DF18747591E5B314C05763EDCD59632423CA83F14D6F073D784DB2B7001643A6760
F9F0DD6DDD0A59E241DC1ED720287896286F5CC3ADDF6C1ADF6ED35F477B0022981E5E1FBFE1BFB8E26B5BA93253275BF6A44B3FA1051CDFE3B3F5D2725A9A580FD5B04525B3182FCD2B3FDA124ACA3C901406A2B55CD8B95D48D13E379F1CCBCDFC39FEE4ACC5523AA0BDEF57E63A1F81CBABA9F45CAAED48D06BFB3D16836042BED57CAC84761BFEB59A0C81304908BB781E4BBDF230D2E977374B97BD0B6B7D38B736428826A0F2729BE2290256DC304E875C9D4B3FB2125AE3D0CD3130D6114989517ACA97DAA2485181EB31C07D2C6A5BCC587E048A6D2BEACD6FE206F225C708461B41FDB5AD087C5DC4FCAEEC3A3437A42E51B065D6E4332F71B109D3317681AB0FCBF31C9F1C23BA46B4F983AF9214D13AC3DDF6C03F3E9854C4D47741A5576812BE0B5CB8BF647B930687EC881DF76191F9C468C1736EEF1E59635EB6CBD2C73B00068C8FFEDEDEC2826D114DC1F8824924FA079056E25A5DDBAECEB90A18C51F919A83AE980E25BF06DD486427DFDEE6F708AA642625CE4C4298AFDD7AC48AA81B0C5608C2D801543EDEEAB5479C1342E4E4AEC719F1A46E33C1D761EFDF22116051E18FA714C72FAE0756835527748E4DF2E728E3DAAF94E9B3F37489C0D4E12D40469296D35673027F5E4D70D54B668A7C00F96CCB23F2562A468B650A1719186285BE1893B861E8B2E3E49EEA5F37799FE4DFC738F99E140F8E31D1B21E9882867563C9BC24A39A2195266D87B203
………
数据量非常大,也就说明不用传统的方式去解决以上问题,需要用一个新的方式去降低算法复杂度
在这里百度了一会,发现十六进制转二进制再转八进制,可以明显减少算法复杂度
思路是:十六进制数的每一位相当于一个四位二进制,同时八进制数每一位相当于三位二进制数,于是,只要把二进制数的每一位存到char型数组中,然后三位三位一取,并把确实的0补上去,就可以完成。
//代码已经通过测试,以下代码为借鉴的代码
//http://www.jianshu.com/p/e06bac9c9231
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
new Main().systemScanner();
}
public void systemScanner() {
Scanner jin = new Scanner(System.in);
while (jin.hasNext()) {
int length = jin.nextInt();
for (int i = 0; i < length; i++){
String strTmp=jin.next();
tranform(strTmp.toCharArray(), strTmp.length());
}
}
}
/*
* 3位16进制等价于4位8进制
*/
int[] stack=new int[40000];
public void tranform(char[] str, int length) {
char[] buff = new char[4];
int top = -1;
for (int i = length - 1; i >= 0; i -= 3) {
int sum = 0;
for (int j = 0; j < 3 && i - j >= 0; j++) {// i-j>=0防止不够三个的情况
int tmp = str[i - j] >= '0' && str[i - j] <= '9' ? str[i - j] - '0'
: str[i - j] - 'A' + 10;//区分是数字,还是字符,进行对应转换
sum+=(tmp<<(4*j));//这句很重要,通过这句就可以从16变成10进制了,不过,不知道为什么?是如何得出的呢?
}
stack[++top]=sum;//sum的结果是16进制转化10进制的结果,每3个16进制变成10进制,再变8进制
}
while(stack[top]==0){//排除前导为0的判断
top--;
}
// for(int i=top;i>=0;i--){//直接输出会丢失前导0,因为此转化成8进制并不是最左边的情况,应该保留0
// System.out.print(Integer.toOctalString(stack[i]));//从10进制转化成8进制
// }
for(int i=top;i>=0;i--){
String str1=Integer.toOctalString(stack[i]);//从10进制转化成8进制
if(i!=top&&str1.length()<4){
//不是最左边的一个,就不用去掉前导0,而默认是去掉0的,所以要进行补会
for(int y=0;y<4-str1.length();y++)
System.out.print("0");
}
System.out.print(str1);
}
System.out.println();
}
}
另一种用java的做法:
http://blog.csdn.net/yl_freedom/article/details/41650523
或者是像下面这样做:(C/C++)
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n = 0, i = 0, j = 0, temp = 0, nNum = 0;
char ch;
string strHex[10];
string strBin[10];
string strOct[10];
cin>>n;
for (i = 0; i < n; ++i)
{
cin>>strHex[i];
}
//十六进制转二进制
for (i = 0; i < n; ++i)
{
j = 0;
while (strHex[i][j])
{
switch(strHex[i][j])
{
case '0': strBin[i] += "0000"; break;
case '1': strBin[i] += "0001"; break;
case '2': strBin[i] += "0010"; break;
case '3': strBin[i] += "0011"; break;
case '4': strBin[i] += "0100"; break;
case '5': strBin[i] += "0101"; break;
case '6': strBin[i] += "0110"; break;
case '7': strBin[i] += "0111"; break;
case '8': strBin[i] += "1000"; break;
case '9': strBin[i] += "1001"; break;
case 'A': strBin[i] += "1010"; break;
case 'B': strBin[i] += "1011"; break;
case 'C': strBin[i] += "1100"; break;
case 'D': strBin[i] += "1101"; break;
case 'E': strBin[i] += "1110"; break;
case 'F': strBin[i] += "1111"; break;
default:break;
}
++j;
}
}
//二进制转化为八进制
for (i = 0; i < n; ++i)
{
j = strBin[i].size()-1;//获得长度
while (strBin[i][j] && j>=0)
{
temp = 3;
nNum = 0;
while (temp-- && j>=0)
{
if ('1' == strBin[i][j])
{
switch(temp)
{
case 0: nNum += 4; break;
case 1: nNum += 2; break;
case 2: nNum += 1; break;
default:break;
}
}
--j;
}
strOct[i] += (nNum+'0');
}
}
//字符串逆序
for (i = 0; i < n; ++i)
{
temp = strOct[i].size()-1;
for (j = 0; j <= temp/2; ++j)
{
ch = strOct[i][j];
strOct[i][j] = strOct[i][temp-j];
strOct[i][temp-j] = ch;
}
}
//打印
for (i = 0; i < n; ++i)
{
j = 0;
while (strOct[i][j++] == '0');//跳过前面的0
for(--j; j < strOct[i].size(); ++j)
{
cout<<strOct[i][j]-'0';
}
/*if (i != n-1)*/
cout<<endl;
}
return 0;
}
//http://blog.csdn.net/jiluoxingren/article/details/50478759
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int n=0;
cin>> n;
string* Hex = new string[n];
string tmpOct;
string* Oct = new string[n];
for(int i=0;i<n;i++)
{
int CurBit = 0;
cin>>Hex[i];
tmpOct = "";
Oct[i] = "";
for(int j=Hex[i].size()-3;j>=0;j-=3)
{
int d = 0;
for(int k=0;k<3;k++)
{
int t = j+k;
// 16 To 10
if(Hex[i][t]>='0' && Hex[i][t]<='9')
{
CurBit = Hex[i][t]-'0';
}
if(Hex[i][t]>='A' && Hex[i][t]<='F')
{
CurBit = Hex[i][t]-'A'+10;
}
d = d * 16 + CurBit;
}
// 3bit hex to 4bit oct
int base = 7; // 111B
for(int k=0;k<4;k++)
{
tmpOct += (char)('0' + (d & base));
d = d >> 3;
}
d = 0;
}
// last less three
int rest = Hex[i].size() % 3;
if(rest != 0)
{
int d = 0;
for(int k=0;k<rest;k++)
{
// 16 To 10
if(Hex[i][k]>='0' && Hex[i][k]<='9')
{
CurBit = Hex[i][k]-'0';
}
if(Hex[i][k]>='A' && Hex[i][k]<='F')
{
CurBit = Hex[i][k]-'A'+10;
}
d = d * 16 + CurBit;
}
int base = 7; // 111B
int max = ceil(4.0 / 3.0 * rest);
// 1bit hex = 4/3 bit oct
for(int k=0;k<max;k++)
{
if(((k==max-1) && (d & base)!=0) || k<max-1)
tmpOct += char('0' + (d & base));
d = d >> 3;
}
}
int j=tmpOct.size()-1;
// turn order
for(;j>=0;j--)
{
Oct[i] += tmpOct[j];
}
}
for(int i=0;i<n;i++)
{
cout<<Oct[i]<<endl;
}
cin>>n;
return 0;
}
//代码逻辑略复杂
//http://blog.csdn.net/sr_19930829/article/details/18677037
#include <iostream>
#include <string.h>
#include <stack>
using namespace std;
int fib(int n)//计算2的多少次方
{
int sum=1;
if(n==0)
return 1;
else
{
for(int i=1;i<=n;i++)
sum*=2;
return sum;
}
}
string str[11];
int two[400008];//因为16进制的位数不超过100000,所以换成二进制数位数不超过400000
int main()
{
int n,i,j,k;
cin>>n;
for(int k=1;k<=n;++k)
{
cin>>str[k];
memset(two,0,sizeof(two));
for( i=0;i<str[k].length();++i)//把十六进制的每一位变成4个二进制数,注意存放的顺序
{
if(str[k][i]>='0'&&str[k][i]<='9')
{
int temp=str[k][i]-'0';
int tap=4*(i+1);//把two数组每4个元素为一组,连续,当前的十六进制位为two数组的最大下标+1
while(temp)
{
two[--tap]=temp%2;//首先要tap-1,因为two数组是从0开始的,这也解释了为什么上面说是最大下标+1
temp/=2;
}
}
else
{
int temp=str[k][i]-55;//A-55得10
int tap=4*(i+1);
while(temp)
{
two[--tap]=temp%2;
temp/=2;
}
}
}//到目前为止把16进制转成了二进制
int count=0;//二进制数三位一组来转化为8进制
int sum=0;//连续三位二进制数的值
stack<int>q;
for(j=4*str[k].length()-1;j>=0;--j)//从two数组的存数的最大下标开始处理,每三个为一组,转化为8进制,保存在栈中
{
sum+=(two[j]*fib(count++));
if(count==3)
{
q.push(sum);
sum=0;
count=0;
}
}
int sum1=0;//考虑处理的末尾,可能最后一组少于3个,有可能是一个,也可能是两个,单独处理,单独输出
int c=0;
for(int m=4*str[k].length()%3-1;m>=0;--m)//4*str[k].length()%3判断还剩下几个
{
sum1+=two[c++]*fib(m);
}
if(sum1!=0)
cout<<sum1;//单独输出
if(q.top()==0)
q.pop();//去除前导0,如果有的话
while(!q.empty())
{
cout<<q.top();//从栈中输出
q.pop();
}
cout<<endl;
}
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin>>n;
for(int k=1;k<=n;k++)
{
string s1,s2;//s1为输入的原始的十六进制串,s2为转化成的二进制串
cin>>s1;
s2="";//初始化
for(int i=0;i<s1.length();i++)//遍历,字符串上加上每一位
{
switch(s1[i])
{
case '0':s2+="0000";break;
case '1':s2+="0001";break;
case '2':s2+="0010";break;
case '3':s2+="0011";break;
case '4':s2+="0100";break;
case '5':s2+="0101";break;
case '6':s2+="0110";break;
case '7':s2+="0111";break;
case '8':s2+="1000";break;
case '9':s2+="1001";break;
case 'A':s2+="1010";break;
case 'B':s2+="1011";break;
case 'C':s2+="1100";break;
case 'D':s2+="1101";break;
case 'E':s2+="1110";break;
case 'F':s2+="1111";break;
default:break;
}
}
int len=s2.length();
if(len%3==1)//三个二进制为一位八进制,二进制串前面补0,确保二进制串的长度为3的倍数
s2="00"+s2;
else if(len%3==2)
s2="0"+s2;
int flag=0;
for(int i=0;i<=s2.length()-3;i+=3)
{
int num=4*(s2[i]-'0')+2*(s2[i+1]-'0')+(s2[i+2]-'0');
if(num)
flag=1;//忽略前导0
if(flag)
cout<<num;
}
cout<<endl;
}
return 0;
}
//http://blog.csdn.net/u011669700/article/details/18563955
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int stack[40000];
void transform(string str, int length)
{
char buff[4];
int top = -1;
for(int i = length - 1; i >= 0; i -= 3)
{
int sum = 0;
for(int j = 0; j < 3 && i - j >= 0; j++)
{
int temp = str[i - j] >= '0' && str[i - j] <= '9' ? str[i - j] - '0' : str[i - j] - 'A' + 10;
sum += (temp << (4 * j));
}
stack[++top] = sum;
}
while( stack[top] == 0)
{
top--;
}
for(int i = top; i >= 0; i--)
{
printf("%04o", stack[i]);
}
cout<<endl;
}
int main()
{
string *str;
int n;
cin>>n;
str = new string[n];
for(int i = 0; i < n; i++)
{
cin>>str[i];
}
for(int i = 0; i < n; i++)
{
transform(str[i], str[i].size());
}
return 0;
}