1010 Radix (25分)
Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer isyes
, if 6 is a decimal number and 110 is a binary number.
Now for any pair of positive integersN1andN2, your task is to find the radix of one number while that of the other is given.
Input Specification:
Each input file contains one test case. Each case occupies a line which contains 4 positive integers:
N1 N2 tag radix
HereN1
andN2
each has no more than 10 digits. A digit is less than its radix and is chosen from the set { 0-9,a
-z
} where 0-9 represent the decimal numbers 0-9, anda
-z
represent the decimal numbers 10-35. The last numberradix
N1
iftag
is 1, or ofN2
iftag
is 2.
Output Specification:
For each test case, print in one line the radix of the other number so that the equationN1
=N2
is true. If the equation is impossible, printImpossible
. If the solution is not unique, output the smallest possible radix.
Sample Input 1:
6 110 1 10
Sample Output 1:
2
Sample Input 2:
1 ab 1 2
Sample Output 2:
Impossible
2020/8/21 19:35
感想
這道題,我感覺有點難,主要是坑點比較多,做了也很長時間,最後看的題解AC的,單靠我自己真做不出來(我是廢物)
坑點
1.進位制
剛一開始做題的時候,我以為進位制只有0-35,因為題目也說了(0-9,a-z),然而卻不是這樣。
題目所說的0-9a-z是題目所給的資料。比如測試資料1af8,我們只能確定這個數的進位制最低是16(min_radix),但是卻不能確定進位制的上限
(比如對於資料‘8’而言,它可能是9進位制,也可能是10進位制,也可能是1000進位制)
現在來討論進位制的上限(max_radix)
那麼現在在題目中,給出了兩個數,一個數記為a是已知進位制的,另一個記為b未知,假設a=675,為10進位制,b=1,未知進位制
很顯然,b的最低進位制min_radix是2
那麼b的最高進位制max_radix 是多少呢
我們的目的是讓a=b,b不可過小也不可過大
假設 max_radix=1000
很顯然b = 1(1000) = 1000 > a = 675
所以,發現了嗎
想讓a=b,b的最大進位制就是a的值,即675
因為我舉的例子比較特殊,如果b不為1,那麼就很難直接得到b的精確的最高進位制max_radix
但是 ,可以肯定的是,當b為1 的時候,max_radix是最大的(因為此時b最小)
因此,我們雖然不知道b=10,20,80,13671...時,對應的max_radix是多少,但是,他們一定比b=1對應的max_radix小
那麼我們就可以用最大的max_radix作為進位制的上限,在min_radix 到max_radix中二分查詢
同時需要注意,max_radix>=min_radix
故有 max_radix = max(a,min_radix);
2.查詢
測試的資料會非常大,挨個遍歷是 不現實的
觀察到,在區間[min_radix,max_radix]上,隨著radix的增大,b的值也是逐漸增大,所以整個數列是單調的,可以使用二分查詢
3.資料型別
一開始用的int型別來儲存轉換之後的十進位制數值,這是非常欠考慮的
因為隨著進位制radix的增大(可能達到幾百幾千進位制)一個很短的數就能直接溢位,所以採用longlong型別
實際上,做題就會發現,即使考慮到以上全部,只能得到15/25的分值,剩下的10分就比較細節
當我們使用longlong時,其實還是會資料溢位的,溢位之後,變為負數
所以,二分查詢時的程式碼,就需要改動
當t資料溢位,變成負數,那麼我們也需要認為,t>res,否則二分查詢的邏輯會混亂。因此加上||t < 0(必須放在二分while迴圈的第一個if中)
LL BinarySearch(char s[],LL res,LL left,LL right){ LL flag = 0; while(left<=right){ LL mid = (left+right)/2; LL t = toDecimal(s,mid); if(t > res || t < 0){//此處的if判斷條件非常細節,!!!!!!!! //t<0的情況是longlong溢位 right = mid-1; } else if(t < res){ left = mid+1; } else if(t == res){ flag = mid; right = mid-1; } } return flag; }View Code
附上最後的程式碼
1 #include <bits/stdc++.h> 2 3 #define LL long long 4 5 using namespace std; 6 7 //把字元型別的0-9a-z轉換成整形的函式 8 int toInteger(char s){ 9 if(s>='0'&&s<='9'){ 10 return s-'0'; 11 } 12 else if(s>='a'&&s<='z'){ 13 return s-87; 14 } 15 return 0; 16 } 17 //把字串轉換成對應的radix進位制的函式 18 LL toDecimal(char s[],int radix){ 19 20 int len = strlen(s); 21 LL val=0;//記錄結果 22 int exp = 0;//記錄次冪 23 24 for(int i=len-1;i>=0;i--){ 25 26 int number = toInteger(s[i]); 27 28 val+=number*pow(radix,exp++); 29 } 30 31 return val; 32 } 33 //在最低進位制和最高進位制之間二分查詢 34 LL BinarySearch(char s[],LL res,LL left,LL right){ 35 LL flag = 0; 36 while(left<=right){ 37 38 LL mid = (left+right)/2; 39 LL t = toDecimal(s,mid); 40 if(t > res || t < 0){ 41 //t<0的情況是longlong溢位 42 right = mid-1; 43 } 44 else if(t < res){ 45 left = mid+1; 46 } 47 else if(t == res){ 48 49 50 flag = mid; 51 right = mid-1; 52 } 53 } 54 return flag; 55 } 56 int main(){ 57 char n[2][20]; 58 int tag,radix; 59 60 cin>>n[0]>>n[1]>>tag>>radix; 61 62 tag--; 63 int un_tag = 1-tag; 64 65 //把已知的數轉換成十進位制 66 LL res = toDecimal(n[tag],radix); 67 68 //遍歷,得到最小的可能成立的 radix(進位制) 69 int min_radix = 0; 70 for(int i=0;i<strlen(n[un_tag]);i++){ 71 min_radix = max(min_radix,toInteger(n[un_tag][i])); 72 } 73 min_radix++; 74 75 //得到最大的,radix的上限 76 //max_radix 理解! 77 LL max_radix = max((LL)min_radix,res); 78 //LL max_radix = 6; 79 80 //-----此處應該二分查詢最小的,成立的radix 81 LL flag = BinarySearch(n[un_tag],res,min_radix,max_radix); 82 83 if(flag != 0){ 84 cout<<flag; 85 return 0; 86 } 87 cout<<"Impossible"; 88 return 0; 89 90 91 }