PAT甲级1010 Radix :[C++题解]进制位、秦九韶算法、二分(PAT通过率最低的一道题0.11)
文章目錄
- 題目分析
- 題目鏈接
題目分析
分析:
本題思路分兩步。
第一步:先把給出數(shù)值和進(jìn)制的數(shù),暫定為N1,轉(zhuǎn)換成10進(jìn)制,即為target。
第二步: 判斷一下N2在多少進(jìn)制下是等于target的。
然后看一下數(shù)據(jù)范圍。
給的進(jìn)制數(shù)最大是36進(jìn)制,數(shù)最多是10位,因此N1最大可能是3610<1×101636^{10}< 1 \times 10^{16}3610<1×1016 會爆int,用long long (范圍9×10189 \times 10^{18}9×1018)來存。
第二個數(shù)N2的進(jìn)制數(shù)最大是多少呢? 當(dāng)N2的位數(shù)很少的時候,它的進(jìn)制數(shù)會很大,最大跟N1十進(jìn)制下的最大值差不多,比如(10)radix=1×radix=radix,轉(zhuǎn)化為十進(jìn)制等于radix,而這個radix需要等于N1的十進(jìn)制數(shù)。(10)_{radix}= 1\times radix =radix,轉(zhuǎn)化為十進(jìn)制等于radix,而這個radix 需要等于N1的十進(jìn)制數(shù)。(10)radix?=1×radix=radix,轉(zhuǎn)化為十進(jìn)制等于radix,而這個radix需要等于N1的十進(jìn)制數(shù)。N1的量級在10^16次方上,所以待求的進(jìn)制也需要用long long 來存,否則會爆int。
所以,這里不要誤以為讓求的進(jìn)制也在36之內(nèi),這是錯誤的!!! 待求進(jìn)制數(shù)非常大,會爆int。
經(jīng)過上面的分析,我們已經(jīng)知道待求進(jìn)制數(shù) 在1~targettargettarget之間,枚舉的區(qū)間比較大。
假設(shè) k進(jìn)制下4位數(shù)為:(abcd)k(abcd)_k(abcd)k?,它表示的十進(jìn)制是s=a×k3+b×k2+c×k+ds=a \times k^3 + b \times k^2 +c \times k + ds=a×k3+b×k2+c×k+d
當(dāng)進(jìn)制k變大的時候,這個數(shù)對應(yīng)的十進(jìn)制數(shù)是在變大的。 這是單調(diào)的!!! 所以我們會想到 用二分法來加速枚舉進(jìn)制。
每次二分查找進(jìn)制區(qū)間[1,target][1 , target][1,target]的一個中點mid ,判斷 mid進(jìn)制下得到的十進(jìn)制數(shù) 和 target的關(guān)系,如果小,則 在mid的右側(cè)區(qū)間在二分查找;如果大了,則在mid的左側(cè)區(qū)間繼續(xù)查找進(jìn)制。
這里的左邊界是1不嚴(yán)謹(jǐn),實際上進(jìn)制數(shù)最小值應(yīng)該是 N2中出現(xiàn)的數(shù)字的最大值+1. 比如N2 = 123 那么這個數(shù)的進(jìn)制最小也是 3+1 =4進(jìn)制。
所以,我們可以二分查找第一個大于等于target這個數(shù)的進(jìn)制mid。如果這個數(shù)等于target說明有解,否則說明無解。
ac代碼
#include<bits/stdc++.h> using namespace std;typedef long long LL;//0到z的字符表示:映射成 int型的 0 到35 整型數(shù) int get(char c){if(c <= '9') return c-'0';return c-'a'+10; // a~z 映射到10~35 }// r進(jìn)制轉(zhuǎn)化為 十進(jìn)制 LL calc(string a , LL r){LL res = 0;for(auto c: a){//如果計算出來的結(jié)果很大,大于long long 說明肯定無解,因為進(jìn)制數(shù)不超過1e16//此時僅需要返回1個大的數(shù)即可if((double)res *r + get(c) > 1e16) return 1e18;res = res * r + get(c); //秦九韶算法 求十進(jìn)制數(shù)}return res; }int main(){string n1,n2; //兩個數(shù)cin>>n1>>n2;int tag ,radix; //進(jìn)制cin>>tag >> radix;//目的是讓n1已知,n2待求。if(tag==2) swap (n1 ,n2); LL target = calc(n1, radix); // 計算十進(jìn)制下是多少//二分查找一個合適的進(jìn)制LL l =1, r = target+1; //進(jìn)制的最大值是target+1.//求進(jìn)制的最小值for(auto c: n2) l =max(l , (LL)get(c)+1); while(l<r){LL mid = l +r >> 1;if(calc(n2,mid)>=target) r=mid;else l = mid +1;}//while退出的時候l ==r//大于等于target的第一個數(shù) if(calc(n2, r)!=target){cout<<"Impossible";}else cout<<r<<endl;}補充:
秦九韶算法 用來快速求其他進(jìn)制轉(zhuǎn)換為十進(jìn)制的值是多少。
// r進(jìn)制轉(zhuǎn)化為 十進(jìn)制 //a中存的是r進(jìn)制數(shù)數(shù)值, r表示進(jìn)制 LL calc(string a , LL r){LL res = 0;for(auto c: a){res = res * r + get(c); //秦九韶算法 求十進(jìn)制數(shù)}return res; }上面用到的get函數(shù)是用來將字符轉(zhuǎn)變成數(shù)字,比如a變成10
//0到z的字符表示:映射成 int型的 0 到35 整型數(shù) int get(char c){if(c <= '9') return c-'0';return c-'a'+10; // a~z 映射到10~35 }
來源:維基百科
比如m進(jìn)制數(shù)abcd轉(zhuǎn)換成十進(jìn)制數(shù)是多少?
r=0; r= r*m +a; r= r*m+b; r=r*m+c; r=r*m+d; 可以用循環(huán)來寫十進(jìn)制轉(zhuǎn)化為其他進(jìn)制:帶余除法。
題目鏈接
PAT甲級1010 Radix
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的PAT甲级1010 Radix :[C++题解]进制位、秦九韶算法、二分(PAT通过率最低的一道题0.11)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PAT甲级1136 A Delayed
- 下一篇: PAT甲级1015 Reversible