PAT 1010 Radix

1010 Radix (25分)

Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is yes, if 6 is a decimal number and 110 is a binary number.

Now for any pair of positive integers N1 and N2, 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
Here N1 and N2 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, and a-z represent the decimal numbers 10-35. The last number radix is the radix of N1 if tag is 1, or of N2 if tag is 2.

Output Specification:

For each test case, print in one line the radix of the other number so that the equation N1 = N2 is true. If the equation is impossible, print Impossible. 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
 
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
 
 

思路

这题的有非常多坑。
坑点:
假设输入为 a b 1 radix ,根据题意,此时就要求使得a=b时,b的基数r :
1. a, b有字母a-z,所以应该用string表示这两个数,数最长为10位,所以int范围不够,比如10个z,所以a或b对应的十进制数据类型应该为long long。

2. r不一定是2-36,就比如8可以是九进制也可以是十进制,所以就要确定r的范围:

 r的下界肯定是b中最大那一位+1,就比如158至少是9进制。

   r的上界肯定不超过待比较的数对应的十进制数值,比如150 11251240 1 10,结果肯定不可能比150还大,

   但是有一种特殊情况,比如8 8 1 10,运行结果就应该是9,

   所以r的上界应该是(a)10+1,(a)10表示a对应的十进制的值

 因为(a)10是long long类型,可能不止十位数,所以使用顺序查找肯定会超时,这里已知上下界了,因此要使用二分查找。

3. 但是采用二分法查找的时候,比如150 11251240 1 10,结果肯定不可能比150还大,但是二分mid为75的时候,有可能算出来的数已经大于long long的范围,已经溢出了,怎么处理溢出呢?溢出之后会变成最大负数,比如四位有符号数(计算机里面是补码表示) 的最大值是0111,也就是7,当大于7的时候就会溢出变成负数,比如为8时,就是1000,注意这里是补码,1000就是-8。那么只要是取值为负的,全部是上溢,说明基数取得过大了, 此时二分的时候就要往左边那一半找。

(经过大量提交,可以得出结论:题目中给出测试点的已知基数不会溢出)

  

结合以上分析,参考了网上许多大神的代码,终于是通过了,只能说这道题看似简单,但是想拿全部 25分,有难度。 

 
  1 #include <iostream>
  2 #include <stdio.h> 
  3 #include <string>
  4 
  5 using namespace std;
  6 
  7 // 获取每一位数的字符转成数字的值 
  8 long long getDigitValue(char n)
  9 {
 10     if(n >= '0' && n <= '9')
 11         return n-'0';
 12         
 13     // a-z 对应 10-35 
 14     if(n >= 'a' && n <= 'z')    
 15         return n-'a' + 10;    
 16         
 17     return -1;
 18 } 
 19 
 20 // 把radix进制转为十进制 
 21 long long toDecimal(string num, long long radix)
 22 {
 23     long long sum = 0;
 24     long long k = 1;
 25     long long i = num.length()-1;
 26     for(; i >= 0; --i)
 27     {
 28         long long val = getDigitValue(num[i]);
 29         sum += val * k;
 30         k *= radix;
 31     }
 32     
 33     return sum;
 34 }
 35 
 36 int main()
 37 {
 38     string a, b;
 39     long long tag, radix;
 40     cin >> a >> b >> tag >> radix;
 41     
 42     if(tag == 1)
 43     {
 44         long long decimal_a = toDecimal(a, radix); 
 45         long long left = getDigitValue(b[0]);
 46         for(long long i = 1; i < b.length(); ++i)
 47         {
 48             long long val = getDigitValue(b[i]);
 49             if(val > left)
 50                 left = val;
 51         }
 52         // 基数的下界是最大的那个数字加上1
 53         // 就比如158肯定不能是8进制,至少是9进制 
 54         left += 1;    
 55         
 56         // 基数的上界是另一个要比较的数字+1(这里就是decimal_a+1) 
 57         // 另一个要比较的数字(比如10个z)可能超出int范围,所以这里要用long long
 58         long long right = decimal_a+1; 
 59         // 二分查找 
 60         while(left <= right)
 61         {
 62             int mid = (left+right)/2;
 63             long long decimal_b = toDecimal(b, mid);
 64             if(decimal_a == decimal_b)
 65             {
 66                 cout << mid;
 67                 return 0;
 68             }
 69             else if(decimal_a < decimal_b || decimal_b < 0)
 70                 right = mid-1;
 71             else
 72                 left = mid+1;
 73         } 
 74     }
 75     else
 76     {
 77         long long decimal_b = toDecimal(b, radix);
 78         
 79         long long left = getDigitValue(a[0]);
 80         for(long long i = 1; i < a.length(); ++i)
 81         {
 82             long long val = getDigitValue(a[i]);
 83             if(val > left)
 84                 left = val;
 85         }
 86         left += 1;    
 87         
 88         long long right = decimal_b+1; 
 89         // 二分查找 
 90         while(left <= right)
 91         {
 92             long long mid = (left+right)/2;
 93             long long decimal_a = toDecimal(a, mid);
 94             if(decimal_a == decimal_b)
 95             {
 96                 cout << mid;
 97                 return 0;
 98             }
 99             else if(decimal_b < decimal_a || decimal_a < 0)
100                 right = mid-1;
101             else
102                 left = mid+1;
103         } 
104     }
105         
106     cout << "Impossible";
107     
108     return 0;
109 }
原文地址:https://www.cnblogs.com/FengZeng666/p/12601356.html