1. 程式人生 > 實用技巧 >1010 Radix (25分)

1010 Radix (25分)

1010Radix(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 integersN1​​andN2​​, 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

HereN1andN2each 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-zrepresent the decimal numbers 10-35. The last numberradix

is the radix ofN1iftagis 1, or ofN2iftagis 2.

Output Specification:

For each test case, print in one line the radix of the other number so that the equationN1=N2is 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 }