任意進制的轉換(針對大數而言)

在數據結構課關於棧的這一章中,咱們都學過用「模2取餘法」來將一個10進制數轉換爲一個二進制數,進而能夠推廣到「模n取餘法」,經其轉換爲n進制(n任意指定)。確實,這是一個很基礎的題目,可你是否想過若是這個10進制數是一個大數(其位數可能上千位,此時用通常數據類型確定是會溢出的),那麼這個問題又如何來求解呢?c++

固然,也許你會說很簡單嘛,本身寫一個大數類(固然至少要寫一個大數除法才行),或者你用的是Java這種現代化語言,就更輕鬆了,直接用BigInteger這樣的大數類就能夠來表示一個大數,進而用書上教的方法來實現。算法

可是,真的須要用到大數類嗎?事實上,「殺雞焉用牛刀「,咱們在紙上模擬一番上述運算後就能夠發現,只要作一些小小的改進,就能夠在不使用大數的狀況下,也能夠經過「模n數組

取餘」的原理來實現大數的進制轉換的。(固然,總體的思想仍然是「模n取餘」原理!!!)。數據結構

舉個簡單的例子,就好比說把10進制數12轉換爲2進制形式,書上的方法能夠用下圖來表示spa

按照 「先餘爲低位,後餘爲高位「這條鐵律,其結果爲1100..net

這是書上教咱們的常規思路(惋惜按這個的話,大數是無法考慮的,由於假如這裏不是12,而是一個1000位的大數,因爲是是對大數的總體進行取餘運算,不使用大數類及其設計

除法操做,又如何得以進行呢?),可咱們的目的是不使用大數類,那麼如今咱們就來換一個視角來看這個問題,12是一個十位數,十位上是1,個位上是2,按照咱們正常的code

思惟來看,這個計算應該是下面這樣的:blog

那麼咱們發如今第一輪運算時,十位上的1做爲被除數,2做爲除數,獲得的商是0,餘數是1(能夠斷言只考慮當前這一個數位的計算,餘數或是0,或是1,如果1的話,則進ci

下一數位(這裏即對個位進行運算)時,要用1乘上進制(這裏是10)再加上下一個數位上的值(這裏是2)),即獲得運算進入個位時被除數是12,除數是2,獲得的商是6,

數是0。第一輪運算的結果是商是06,餘數是0.

進入第二輪運算,則上一輪的商6(這裏首先要去掉前面多餘的0)變成本輪的被除數,如此下去,便可獲得每輪的餘數。

推廣開來,若是被除數是一個1000位的大數,例如「12343435154324123……342314324343」

那麼咱們照樣能夠從第一個數位開始逐位考慮,好比第一位是1(做爲被除數),2是除數,獲得的商是0,餘數是1,而後是第二個數位2,因爲上一位留下了餘數1,則此時被

除數應該是1*10+2 = 12,因此獲得的商是6,餘數是0,即運算到此時的商是06,而後是第三個數位3,因爲上一個數位留下的餘數是0,因此此時被除數就是3,。。。如此下去

就完成第一輪的運算,這一輪完畢後,須要把獲得的商變成下一輪的被除數,繼續上述的運算,直到被除數爲0才中止。

下面給出了一個示例代碼,展現瞭如何將一個10進制的大數轉換爲其二進制形式,僅供參考:

 1 #include <stdio.h>
 2 #include <string.h>
 3  
 4 char str[1000];//輸入字符串
 5 int start[1000],ans[1000],res[1000]; //被除數,商,餘數
 6  
 7 //轉換先後的進制
 8 const int oldBase = 10;
 9 const int newBase = 2;
10  
11 void change()
12 {//各個數位還原爲數字形式
13     int i,len = strlen(str);
14     start[0] = len;
15     for(i=1;i<= len;i++)
16     {
17         if(str[i-1] >= '0' && str[i-1] <= '9')
18         {
19             start[i] = str[i-1] - '0';
20         }
21     } 
22 }
23  
24 void solve()
25 {
26     memset(res,0,sizeof(res));//餘數初始化爲空
27     int y,i,j;
28     //模n取餘法,(整體規律是先餘爲低位,後餘爲高位)
29     while(start[0] >= 1)
30     {//只要被除數仍然大於等於1,那就繼續「模2取餘」
31         y=0;
32         i=1;
33         ans[0]=start[0];
34         //
35         while(i <= start[0])
36         {
37             y = y * oldBase + start[i];
38             ans[i++] = y/newBase;
39             y %= newBase; 
40         }
41         res[++res[0]] = y;//這一輪運算獲得的餘數
42         i = 1;
43         //找到下一輪商的起始處
44         while((i<=ans[0]) && (ans[i]==0)) i++;
45         //清除這一輪使用的被除數
46         memset(start,0,sizeof(start));
47         //本輪獲得的商變爲下一輪的被除數
48         for(j = i;j <= ans[0];j++)
49             start[++start[0]] = ans[j]; 
50         memset(ans,0,sizeof(ans)); //清除這一輪的商,爲下一輪運算作準備
51     } 
52 }
53  
54 void output()
55 {//從高位到低位逆序輸出
56     int i;
57     for(i = res[0];i >= 1;--i)
58     {  
59         printf("%d",res[i]);
60     }
61     printf("\n"); 
62 }
63  
64 int main()
65 {
66     scanf("%s",str);
67     change();
68     solve();
69     output();
70     return 0;
71 }

接下來讓咱們將次算法具體應用到題目中:

題目地址:https://ac.nowcoder.com/acm/contest/910/C

題目描述

給出一個m進制下的數a,如今請輸出a在n進制下的表示。

輸入描述:

第一行一個整數T,表明有T組數據

接下來T行:

每一行有3個整數,分別表示m,n,a,其中2=<m<=62,2=<n<=62,a的位數不超過350位且a>=0,樣例個數不超過400。

輸出描述:

輸出上述問題的答案,每一個答案佔一行。
示例1

輸入

1
10 2 3

輸出

11

hashch[]與hashnum這兩個數組我以爲設計的很是好!
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=5000+100;
 4 char hashch[maxn];
 5 int hashnum[maxn];
 6 void init()
 7 {
 8     char ch;
 9     for(int i=0;i<62;i++){
10         if(i<10)                ch=i+'0';
11         else if(i>=10&&i<36)    ch='A'+i-10;
12         else                    ch='a'+i-36;
13         hashch[i]=ch;
14         hashnum[ch]=i;
15     }
16 }
17 string change(int m,int n,string str)
18 {
19     bool flag;
20     string ans="";
21     int tmp,quotient,remainder;
22     while(true)
23     {
24         flag=false;
25         remainder=0;
26         string div="";
27         int len=str.length();
28         for(int i=0;i<len;i++){
29             tmp=remainder*m+hashnum[str[i]];
30             quotient=tmp/n;
31             remainder=tmp%n;
32             if(flag){
33                 div+=hashch[quotient];
34             }
35             else{
36                 if(quotient!=0){
37                     flag=true;
38                     div+=hashch[quotient];
39                 }
40             }
41         }
42         ans=hashch[remainder]+ans;
43         str=div;
44         if(flag==false) break;
45     }
46     return ans;
47 }
48   
49 int main()
50 {
51     init();
52     int t;
53     scanf("%d",&t);
54     while(t--){
55         int m,n;
56         string str;
57         cin>>m>>n>>str;
58         string ans=change(m,n,str);
59         cout<<ans<<endl;
60     }
61     return 0;
62 }

 

參考文獻:

https://blog.csdn.net/SJF0115/article/details/8690581

相關文章
相關標籤/搜索