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
题型分类:二分法、进制转换
题目大意:输出两个数,给出一个数的进制,判断另一个数在什么进制的情况下与前一个数相等。
解题思路:思路大致为,采用十进制作为桥梁,比较两个数是否相等。这题较难,已AC,接下来说一下这题的难点:
1.首先要想到得出进制的上下限,下限一定是比最小的元素要大1(比如 135a5 这个数,那么他的最小进制一定是11)。题目还写了,当答案不唯一时,输出最小的进制。这个告诉我们什么呢?首先我们先思考一下,什么时候会答案不唯一,只有在一个数字时,才会答案不唯一(比如说一个数是6,那么6这个数在7进制,8进制等等比7大的进制下,最后的十进制数都是6)。所以我们在选取上限时,有两个限制条件:条件一是上限要≥下限,这个是显然的;条件二是在答案不唯一时,要选取小的进制作为答案,所以第二限制条件是十进制的另一个需要比较的数,也就是代码段中的high = max(low, decimalN1)。
2.二分法的写法要注意,并且在判断两个数是否相等时,如果数据变为负数,说明进制选取过大,超出了long long的表示范围。
3.题目不能选用int,要用long long来保存数据,因为int的范围不够表示。
#include <iostream>
#include <algorithm>
#include <string>
#include <cctype>
using namespace std;
long long toDecimal(string N, int radix);
long long getLow(string N);
int main(int argc, char** argv) {
string N1, N2;
int tag, radix;
cin >> N1 >> N2 >> tag >> radix;
if(tag == 2) swap(N1, N2); //当tag为2时,交换N1, N2,方便对数据进行统一处理
long long decimalN1 = toDecimal(N1, radix);
long long low = getLow(N2), high = max(low, decimalN1); //分别计算出需要测定进制的上下限,计算上限时,上限一定≥下限,同时题目说明了,当进制不唯一时,输出最小的进制,所以还要加入N1的十进制数作为第二限定条件(此处是难点,多琢磨琢磨)
while(low <= high){ //数据量比较大,采用二分法来压缩时间
long long mid = (low + high) / 2; //mid即测试的进制
long long decimalN2 = toDecimal(N2, mid);
if(decimalN2 < 0 || decimalN2 > decimalN1){ //难点:如果radix太大超出long long型的范围,会使decimalN2变为负数,此时也代表了进制过大
high = mid - 1;
}else if(decimalN2 < decimalN1){ //进制选取的太小
low = mid + 1;
}else{ //找到正确的进制,输出答案
cout << mid;
return 0;
}
}
cout << "Impossible";
return 0;
}
long long toDecimal(string N, int radix){
long long sum = 0;
for(int i = 0; i < N.length(); i++){ //注意数字和字母转换成十进制时公式不一样
if(isdigit(N[i])) sum = sum * radix + N[i] - '0';
else sum = sum * radix + N[i] - 'a' + 10;
}
return sum;
}
long long getLow(string N){ //获得进制的下限
char maxElement = '0';
for(int i = 0; i < N.length(); i++){
if(N[i] > maxElement) maxElement = N[i];
}
return (isdigit(maxElement) ? maxElement - '0' : maxElement - 'a' + 10) + 1; //最小进制一定比最大的元素大1
}