20130619.後來我在網上漫看Matrix67的博客,發現了這篇專門講述進制轉換的,“好嘢大家摞出來分享”,可以先參看:Matrix67《漫話進位置》
原題地址:點擊打開鏈接
這題是目前我見過最難的(對於我來說)進制轉換題,當然對於一些大牛來說想必思路是十分的清晰,可是對於鄙人是十分困難。做題思路是問了周生然後才寫出來的,通過的人數比較多````莫非是水題行列之一?咳咳,不管怎麼說,做這到題對於我的提升還是非常大的,建議各位也思考一下。
看到一個比較神的解法,鏈接在此:點擊打開鏈接
但是我看不懂這個解法的原理……所以我還是用我理解的解法來說好了。
——————正文——————
類比一下正常的進制情況下如何表示一個數?其實就是用進制的不同次冪配上係數,然後組合起來。
說得更本質一點,就是我們要從高位開始“試錯”,看看在當前這個位所能表示的範圍有沒有包含所要求的數,例如:
對於3進制的數,如何表示十進制的10?
1 首先我們試一下只有1位的情況下,能不能表示,1位的情況,最小是0,最大是2,顯然10不在[0,2]這個範圍內,1位無法表示
2 然後試一下有2位的情況,這種情況下,最小是0,最大是2*3^1+2*3^0=8,可見10不在[0,8]範圍內,2位無法表示
3 然後是一下3位的情況,這樣子,最小是0,最大是2*3^2+2*3^1+2*3^0=26,10在[0,26]範圍內,因此在3進制中,3位就必定可以表示十進制中的10
然後從高位往回推,在第三位應該填的數字是多少?假設填k(在3進制下,k必定小於3),那麼k必須滿足(10-k*3^2)<=2*3^1+2*3^0
為什麼呢?填了第3位後,剩下的數是10-k*3^2,如果這個時候不滿足上面的不等式,那麼剩下的兩位是無法繼續表示這個剩餘數的。
取k=1,即第3位添1,那麼剩下10-1*3^2=1;
看看第二位,假設第二位填k1,因爲1<=2*3^0成立,所以k1填0即可,第2位位0
最後一位很簡單了,直接填1就可以了,所以10在3進制中表示就是101.
我相信上面的敘述沒有結束,肯定有人就知道這題的思路是怎麼樣了,沒錯,從地位開始計算,每增加一位,求出當前位置可以表示出的範圍,然後看看要求的n是否在這個範圍內即可,原理和上面一模一樣。同時介紹一下sscanf(不是scanf)這個函數,非常好用,可以自己查下使用方法,或者直接看下面的註釋
那就直接上代碼了,如下:
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<memory.h>
#define MAXX 32770
using namespace std;
char s[50]; //字符串用於讀取輸入
int a[50]; //保存結果
int n,r;
int mp[17][32][3]; //mp[i][j][0]表示-i進制下其j次冪是多少
//mp[i][j][1]表示-i進制下到第j位可表示的最小數
//mp[i][j][2]表示-i進制下到第j位可表示的最大數
bool outside(int index) //到第index位還是不能表示則返回true,否則false
{
if(mp[-r][index][1]>n || mp[-r][index][2]<n)
return true;
return false;
}
char cv(int digit)
{
if(digit<10)
return '0'+digit;
else
return 'A'+digit-10;
}
int main()
{
//freopen("in","r",stdin);
//freopen("out","w",stdout);
for(int i=-2;i>=-16;--i)
{
int j=0;
int mu=-i-1;
mp[-i][j][0]=1;
mp[-i][j][1]=0;
mp[-i][j][2]=mu;
while(abs(mp[-i][j][0])<=MAXX)
{
j++;
mp[-i][j][0]=mp[-i][j-1][0]*i;
if(mp[-i][j][0]>0)
{
mp[-i][j][1]=mp[-i][j-1][1];
mp[-i][j][2]=mp[-i][j-1][2]+mp[-i][j][0]*mu;
}
else
{
mp[-i][j][1]=mp[-i][j-1][1]+mp[-i][j][0]*mu;
mp[-i][j][2]=mp[-i][j-1][2];
}
}
}//預處理完畢,不是必要的,但是測試數據多時跑起來會快一點
while(scanf("%s",s)!=EOF)
{
if(s[0]=='#')
break;
sscanf(s,"%d",&n); //這是個非常方便的函數
//直接將字符串內容作爲輸入
//尤其適合於字符串轉數字
scanf("%d",&r);
int i=0;
memset(a,0,sizeof(a));
while(mp[-r][i][1]>n || mp[-r][i][2]<n)
i++;
for(;i>=1;i--)
{
a[i]=0;
while(outside(i-1))
{
n-=mp[-r][i][0];
a[i]++;
}
}
a[0]=n;
i=31;
while(a[i]==0) i--;
if(i<0) i=0;
for(;i>=0;--i)
printf("%c",cv(a[i]));
printf("\n");
}
}
******<轉載說明>******
轉載註明:誠實的偷包賊
原文地址:http://blog.csdn.net/fanfank/article/details/8983754
******<轉載說明/>******