蓝桥杯-十六进制转八进制

来源:互联网 发布:windows账号登陆 编辑:程序博客网 时间:2024/05/29 04:53

蓝桥杯原题

这个题还是有点含金量,第一遍做出来,很可能会超时,比如以下代码:

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/e06bac9c9231import 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;  }  
0 0
原创粉丝点击