1010. Radix
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 10Sample Output 1:
2Sample Input 2:
1 ab 1 2Sample Output 2:
Impossible
解释说明:
为了方便起见,假定tag=1。 radix 表示的一个数的进制,tempRadix表示第二个数的进制,number表示第一个数在进制radix下的值,tempNum表示第二个数在tempRadix进制下的值。
策略一、用穷举法,计算另一个数的进制,进制值从2开始递增,一旦发现该进制过大,则输出Impossible
该办法仅适用数比较小的情况,当number较大时,会超时。测试用例7会超时。
策略二、用二分法,
最小可能进制minRadix为另一个数中最大的字符对应的数加一(ab 对应 12,96 对应 10),
最大可能进制maxRadix=(number+1)>(minRadix+1)?(number+1):(minRadix+1)
该方法由于可能出现非常大的进制,因此计算该进制下第二个数的值时会产生溢出(就算用了long long类型还是会的,100^10 > 2^64 .....) ,进而导致第二个数的值为负值,二分的逻辑就认为进制还不够大,然后就悲剧了。。。。
试试下面两个测试用例吧:
10000 10 1 28 ---> 614656
10000 96100 1 28 ---> 16
解决方案:
还是用二分法吧,当出现溢出时,特殊处理一下就好了。
将字符串转换为数值的函数如下:
long long strToNumber(char str[MAX_N],long long radix){
int len=strlen(str);
long long number = 0;
long long weight = 1;
for(int i=len-1;i>=0;i--){
number += weight*charToNum[str[i]];
if((number < 0) || (weight*charToNum[str[i]] < 0)){//如果溢出了返回-1
return -1;
}
weight *= radix;
if((weight < 0) && (i > 0)){//如果溢出了返回-1
return -1;
}
}
return number;
}
二分查找部分特殊处理:
//改用二分查找
long long tempRadix;
long long tempNum;
bool noWay = true;
long long maxRadix,minRadix;
minRadix = findMinRadix(n2);
maxRadix = (number+1)>(minRadix+1)?(number+1):(minRadix+1);
tempRadix = minRadix;
while(minRadix <= maxRadix){
tempNum = strToNumber(n2,tempRadix);
if(tempNum == -1){//发现溢出时,进制过大了!
maxRadix = tempRadix - 1;
}else{
if(tempNum > number){
maxRadix = tempRadix-1;
}else if(tempNum < number){
minRadix = tempRadix+1;
}else{
noWay = false;
break;
}
}
tempRadix = (minRadix+maxRadix)/2;
}