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
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
2
1 ab 1 2
Impossible
思路
这题的有非常多坑。坑点:
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 }