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
注意事项:
1、题目中说以0-9和a-z表示0-35,很容易就误认为最大进制为36,但事实上最大进制可能远远大于36。最开始我在实现时就简单地使用了for循环从2开始遍历到10,但事实上这即忽略了上界又忽略了下界。如何确定上下界呢?
下界:最大数位的值加1,如1001的下界为2,6007的下界为8;
上界:将已知进制的数(N1或N2)转化为十进制的值N,与下界中较大的那一个再加1。
2、在将N1或N2转换为十进制时可能会发生溢出,如何判断呢?
转换后小于0即溢出,此时说明当前进制太大,right应变为mid-1。
3、使用long long类型,注意不要一些变量用int,一些用long long,尽量统一使用long long,这样就不用花时间在long long类型和int类型之间的转换上。
4、使用for循环挨个判断,测试点7会超时,需要使用二分法。
参考解法:
#include <stdio.h>
#include <string.h>
char num[2][11];
long long n;
long long changeIntoNum(long long tag, long long radix)
{
long long res = 0;
for(int i = 0; i < strlen(num[tag]); i++)
{
long long temp;
if(num[tag][i] >= '0' && num[tag][i] <= '9')
{
temp = num[tag][i] - '0';
}
else
{
temp = num[tag][i] - 'a' + 10;
}
res = res * radix + temp;
}
return res;
}
int cmp(long long tag, long long left, long long right)
{
long long mid;
long long cur;
//二分法找最小的进制
while(left <= right)
{
mid = (right + left) / 2;
cur = changeIntoNum(tag, mid);
if(cur == n) return mid;
else if(cur < 0 || cur > n) right = mid - 1;
else left = mid + 1;
}
//使用for循环会超时
// for(int i = left; i <= right; i++)
// {
// if(changeIntoNum(tag, i) == n) return i;
// }
return -1;
}
long long findLargestDigit(long long tag)
{
long long max = 0;
for(int i = 0; i < strlen(num[tag]); i++)
{
long long temp;
if(num[tag][i] >= '0' && num[tag][i] <= '9')
{
temp = num[tag][i] - '0';
}
else
{
temp = num[tag][i] - 'a' + 10;
}
if(temp > max) max = temp;
}
return max + 1;
}
int main()
{
long long tag, radix;
scanf("%s %s %lld %lld", num[0], num[1], &tag, &radix);
tag--;
n = changeIntoNum(tag, radix);
if(tag == 0) tag = 1;
else tag = 0;
long long low = findLargestDigit(tag);
long long high = (low > n ? low: n) + 1;
long long r = cmp(tag, low, high);
if(r != -1) printf("%lld", r);
else printf("Impossible");
return 0;
}