蓝桥杯-十六进制转八进制
来源:互联网 发布: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; }
- 蓝桥杯 十六进制转八进制
- 蓝桥杯--十六进制转八进制。。。
- 蓝桥杯 十六进制转八进制
- 蓝桥杯:十六进制转八进制
- 蓝桥杯 十六进制转八进制
- 蓝桥杯 十六进制转八进制
- 蓝桥杯-十六进制转八进制
- 蓝桥杯-十六进制转八进制
- 蓝桥杯-十六进制转八进制
- 蓝桥杯-十六进制转八进制
- [蓝桥杯]十六进制转八进制
- [蓝桥杯]十六进制转八进制
- 蓝桥杯十六进制转八进制,大数。
- 蓝桥杯基础训练 十六进制转八进制
- 蓝桥杯:十六进制转八进制算法
- 蓝桥杯JAVA 十六进制转八进制
- 关于蓝桥杯十六进制转八进制
- 蓝桥杯 基础训练 十六进制转八进制
- 小程序语音与讯飞语音识别踩坑过程
- STL初识list,vector容器
- 【LeetCode】3Sum Closest
- 有关各种居中的问题总结:
- 长假后快速进入工作状态
- 蓝桥杯-十六进制转八进制
- 最长公共子序列(LCS)
- 赞!VC++编程学会使用D与R版通用调试输出功能,方便排错。
- 1022. Digital Library (30)PAT甲级
- The Letter Carrier's Rounds(UVa 814)
- stm32 移植cJson 注意free释放内存!!
- Download~!(南邮CTF)
- 【LeetCode】Container With Most Water
- ViewAnimator类及其子类的介绍