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、N1,N2,指定N1为2进制,寻找另一个数N2是什么进制时,和N1十进制相等。
2、转化为十进制过程中,会超过int范围,所以用long long。
3、寻找N2进制范围边界,下边界为该数中各位数值最大的一位加一,比如:1a,进制下边界为11;而上边界为N1那位数的十进制,比如:N1:40,且是十进制,则N2上边界为40,为什么呢?因为,当N2只为一位时,如:a时,则N2的进制为任意值(y)时,它值都不会变,都是(a*y^0),当它为任意进制时,都一个样,所以我们不讨论一位的情况;当N2为多位时,如1a,10,423(此处不应该按惯性思维把它当十进制看,应该分开成各位看,满X进制进1);什么情况能找到它上边界呢?当N2是10时(最小的多位),它满足进制为40时,N2=N1;如果进制再大,N2肯定没有任何情况满足两数相等,因为N2已经是最小的多位,再多出任何一位或多任一点值(11),它最后十进制的值肯定大于N1,所以N1的十进制为N2进制的上边界。
3、当N1的十进制(N2上边界)比N2下边界小时,则上边界用下边界,因为会有N1,N2都为一位的情况,如:N1:6,十进制,N2:6;N2的进制是为任意都满足相等,但我们取最小情况,则是下边界。
4、因为N2进制的上边界为N1的十进制数,所以下面查找时,会因为逐个遍历而超时,所以用二分查找,因为N1值肯超过int范围,所以二分查找过程中mid值那些都要用long long。
5、这题做着伤肾啊,莫名难受。
我的代码:
#include<cstdio>
#include<cstring>
long long changeRadix(char n[],int radix)//转化为10进制
{
long long sum = 0,len = strlen(n);
for (int i = 0 ;i < len ;i++)
{
if (n[i] >= 'a' && n[i] <= 'z')
sum = sum * radix + n[i] - 'a' + 10;
else
sum = sum * radix + n[i] - '0';
}
return sum;
}
long long max(long long n1,long long n2)//因为algorithm里的max只是比较int,所以必须自己写个long long的
{
if (n1 > n2)
return n1;
else
return n2;
}
long long getSinglemax(char n[])//获取下边界
{
long long h = 0,len = strlen(n);
for (int i = 0 ;i < len ;i++)
{
if (n[i] >= 'a' && n[i] <= 'z')
h = max(n[i] - 'a' + 10,h);
else
h = max(n[i] - '0',h);
}
return h + 1;
}
long long find_radix(char n[],long long nr)
{
long long left = getSinglemax(n);
long long right = max(left,nr);//获取上边界
while (left <= right)
{
long long mid = (right - left) / 2 + left;
long long temp = changeRadix(n,mid);
if (temp == nr)
return mid;
else if (temp > nr || temp < 0)//temp值long long时也会溢出;过大,溢出可以当小于0判断
right = mid - 1;
else
left = mid + 1;
}
return -1;
}
int main()
{
char n1[15],n2[15];
int tag,radix;
scanf("%s %s %d%d",n1,n2,&tag,&radix);
long long r;
if (tag == 1)
r = find_radix(n2,changeRadix(n1,radix));
else
r = find_radix(n1,changeRadix(n2,radix));
if (r == -1)
printf("Impossible");
else
printf("%lld",r);
return 0;
}