藍橋杯:十六進位制轉八進位制的高效演算法
總算是在提交了11次都錯誤之後,第12次過了。也是無語。現在的演算法,按照藍橋杯系統給的10個測試數,顯示耗時31ms,記憶體佔用3.589MB。
問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~9、大寫字母A~F組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度不超過100000。 輸出格式 輸出n行,每行為輸入對應的八進位制正整數。 【注意】 輸入的十六進位制數不會有前導0,比如012A。 輸出的八進位制數也不能有前導0。 樣例輸入 2 39 123ABC 樣例輸出 71 4435274 【提示】 先將十六進位制數轉換成某進位制數,再由某進位制數轉換成八進位制。
一開始覺得不難,不過反覆寫程式碼都錯,我也是醉了。結果看了一下它的測試資料,說好的【每個十六進位制數長度不超過100000位】,還真是用盡了,最後兩個測試數真的就是100000位。幾次都沒對就看了一下錦囊:先轉成2進位制,再轉成8進位制。恩,確實,100000位的十六進位制數就算是long long都超了,只能是按照字串處理。那好,就先轉成2進位制,再轉8進位制,一開始我是這樣做的:
看到兩邊的雙引號了嗎?我是想告訴大家,我一開始的想法是:所有的過程都是以字串形式的。每個16進位制數(字串形式)轉成4位二進位制數(字串形式)。第二第三行在記憶體上是一樣的,只是在讀取的時候第二行是從右往左每4位是一起是一個16進位制數;而第三行在讀取得時候是從右往左每三位是一個8進位制數。第二行(在記憶體上也是第三行)也是每一位是一個字元儲存起來的字串。
結果很難處理,字串從後往前遍歷很難看,十六進位制數'0'~'9'和'A'~'F'(注意有單引號,都是字元),要用switch對映成“0000"~”1111“(注意有雙引號,是字串)。直接這樣實現的也不是沒有,正如我找到的這篇:http://www.tuicool.com/articles/22I3Ib
但是這樣的實現確實麻煩,關鍵是二進位制字串佔用記憶體很大,switch對映還要考慮補位,因為假設原來的十六進位制數時14位,那麼前12位是48位二進位制數,也就是16個8進位制數,但是剩下的兩個十六進位制數是8位二進位制數,要變成8進位制數要補一個二進位制位(在字串前面加個'0'),這種就是補位。
有沒有更好的實現方法呢?也是看圖,這是我現在的實現方法:
這幅圖簡明地表達了我的實現流程。相比起一個十六進位制數4位二進位制數,3位二進位制數是一位8進位制數;我決定選擇其最小公倍數12,就可以少考慮一些位數問題。例如我選擇2位十六進位制數一起處理,那麼就是8位二進位制數,這樣我在轉換了2個八進位制數之後就會多2個二進位制位,留給下次?那不是自尋煩惱嗎?!所以如圖第一行,我將字串從右往左一次取出三位,然後注意第二行標號A,型別是int了,可以將每一位用atoi求出對應的int數值,然後注意是乘16,因為這些都是16進位制數。因為3位十六進位制數,正好是12位二進位制數,正好是4位8進位制數,就沒有了多出一些二進位制位留下次的問題。而且一次處理3為十六進位制數之後,num就可以重用,就不需要將整個十六進位制數的二進位制數儲存下來了。
轉成int,也就是數值型別,怎麼轉8進位制呢?這時候就要想一下,整數在記憶體中是以二進位制方式存在的,也就是說int型別的資料本身就是二進位制數,那麼要進行與二進位制數相關的操作,當然是位運算了,所以有了第三行標號B的語句。這裡我每一次都是將num跟7進行位與,7正好是111B,將num的低3位取了出來,而高位的都因為與運算歸0了,然後就是怎麼把數字變回相應的字元,因為八進位制數是在'0'~'7'之間,而ASCII碼的數字是連續編號的,所以加'0'(實際上是加了'0'的ASCII碼),再轉成char型別就是對應的字元了。然後是第四行,num自己右移3位,也就是說將剛才用過的最低3位拋棄了,然後是次低的三位變成最低3為,再進行步驟B,顯然步驟B是執行4次,都說了多少遍3個十六進位制數是對應4個八進位制數。
處理完3位十六進位制數,再往前處理三位,直到處理完。而每三位處理,無論前面多出來1位十六進位制數還是2位十六進位制數,他們轉成int之後都是佔用4個位元組,佔用32位(32位二進位制數),而高位沒有的本來就是0,何必自己勞神費心去補呢?
要注意一點,由於是從右往左處理的,最後不能直接輸出資料,要把字串反過來,就有了這段程式碼:
for(;j>=0;j--)
{
Oct[i] += tmpOct[j];
}
最後貼出成品的程式碼:
#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;
}
相關推薦
藍橋杯:十六進位制轉八進位制的高效演算法
總算是在提交了11次都錯誤之後,第12次過了。也是無語。現在的演算法,按照藍橋杯系統給的10個測試數,顯示耗時31ms,記憶體佔用3.589MB。 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式 輸入的第一行為一個正整數n (1<
藍橋杯: 基礎練習 十六進位制轉八進位制
問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~9、大寫字母A~F組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度不超過100000。 輸出格式 輸出n行,每行
藍橋杯(java):特殊迴文數,十進位制轉十六進位制,十六進位制轉十進位制,十六進位制轉八進位制,數列排序
人生不易,生活無趣。一起來找點樂子吧。 特殊迴文數: 問題描述 123321是一個非常特殊的數,它從左邊讀和從右邊讀是一樣的。 輸入一個正整數n, 程式設計求所有這樣的五位和六位十進位制數,滿足各位數字之和等於n 。 輸入格式 輸入一行,包
藍橋杯:BASIC-12 十六進位制轉八進位制
問題描述: 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式: 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~9、大寫字母A~F組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度不超過100000。 輸出格式:
藍橋杯十六進位制轉八進位制
問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~9、大寫字母A~F組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度不超過100000。輸出格式 輸出n行,每行為輸入對應的八進
藍橋杯 基礎練習 十六進位制轉八進位制
基礎練習 十六進位制轉八進位制 時間限制:1.0s 記憶體限制:512.0MB 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。輸入格式
藍橋杯 基礎練習 十六進位制轉八進位制
基礎練習 十六進位制轉八進位制 時間限制:1.0s 記憶體限制:512.0MB 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~
藍橋杯題解-十六進位制轉八進位制-BASIC-12
原題地址:十六進位制轉八進位制 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由09、大寫字母AF組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度
藍橋杯題解-十六進位制轉十進位制-BASIC-11
原題地址:十六進位制轉十進位制 問題描述 從鍵盤輸入一個不超過8位的正的十六進位制數字符串,將它轉換為正的十進位制數後輸出。 注:十六進位制數中的10~15分別用大寫的英文字母A、B、C、D、E、F表示。 樣例輸入 FFFF 樣例輸出 655
2016藍橋杯假期任務之《十六進位制轉八進位制》
問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~9、大寫字母A~F組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度不超過100000。輸出格
藍橋杯 基礎練習 十六進位制轉八進位制(5)超長字串處理
基礎練習 十六進位制轉八進位制 時間限制:1.0s 記憶體限制:512.0MB 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由
藍橋杯-- 基礎練習 十六進位制轉八進位制(大數操作)
基礎練習 十六進位制轉八進位制 時間限制:1.0s 記憶體限制:512.0MB 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n
藍橋杯 練習 Java 十六進位制轉八進位制
第一次寫部落格,有不足之處還請大家多指正 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = n
藍橋杯 基礎練習 BASIC-12 十六進制轉八進制
info div for 限制 class 輸入 字符 字母 res 基礎練習 十六進制轉八進制 時間限制:1.0s 內存限制:512.0MB 問題描述 給定n個十六進制正整數,輸出它們對應的八進制數。輸入格式 輸入的第一行為一個正整數n (1<=n
藍橋杯 基礎練習 十六進制轉八進制
spa tro rgs number 解決 ann ret else if ger import java.util.*;public class Main { public static void main(String[] args) { Scann
p1102 十六進位制轉八進位制
題目 描述 Description 輸入一個不超過100,000位的16進位制數,請轉換成8進位制數。 注:16進位制數中,字母0-9還對應表示數字0-9,字母"A"(大寫)表示10,"B"表示11,…"F"表示15. 比如:16進位制數A10B表示的10進位制數是:1016^
十六進位制轉八進位制
問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。 輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~9、大寫字母A~F組成的字串,表示要轉換的十六進位制正整數,每個十六進位制數長度不
十六進位制轉八進位制的快捷方法——巧用格式化輸入輸出
最近刷題的時候遇到一個基礎題,就是將16進位制數轉為8進位制數。咋一看極其簡單,用二進位制做中介即可,簡單規劃了一下就開始動手了。 問題描述 給定n個十六進位制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為一個正整數n (1<=n<=10)。 接下來n行,每行一個由0~
十六進位制轉八進位制兩種方法
#include "stdafx.h" #include <iostream> #include <string> using namespace std; int main() { int n=0; cin >> n; str
BASIC-12 基礎練習 十六進位制轉八進位制 (c++)兩種解法,轉換2進位制或10進位制。
基礎練習 十六進位制轉八進位制 時間限制:1.0s 記憶體限制:512.0MB 錦囊1 使用二進位制。 錦囊2 先把十六進位制轉成二進位制,每位十六進位制正好