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
题目分析:这道题坑很多,博主由于思维定式第一次还以为最大进制是36(z+1),发现10、11、3、4、5、7测试点死活过不了,后来才发现进制可以取得很大。
1号坑:这个坑比较好发现,就是数据类型要用long long,因为10个数全为z,且进制大一点数据就会超过int的范围;
2号坑:这个进制数也可以取到长整型,那么即便是用长整型声明变量也会溢出,但是这个溢出是可以接受的,这代表这个数很大,具体在代码注释中分析;
3号坑:正是因为进制数比较大,顺序查找会运行超时,需要采用二分查找。
这是其中三个大坑,解决这两个问题,差不多就能AC了。
为了避免代码的重复,采用函数来实现各个功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int transform(char a) //将字符转换成对应的数字,不是ACSII码
{
if(a <= '9' && a >= '0')
return a - '0';
else
return a - 'a' + 10;
}
int minRadix(char a[]) //找到最小的进制数
{
int i, max = -1;
for(i = 0; i < strlen(a); i++)
{
if(transform(a[i]) > max)
max = transform(a[i]) + 1;
}
return max;
}
long long strToNum(char a[], int radix) //将字符串变成10进制数
{
long long num = 0;
int i;
for(i = 0; i < strlen(a); i++)
{
num = num * radix + transform(a[i]);
if(num < 0) //这是当数据溢出时,用-1来表示这个数很大
return -1;
}
return num;
}
void judge(char a[], long long rMax, long long rMin, long long t) //得出结果
{ //rMax, rMin表示a的最大和最小的进制数,t见主函数
long long rTmp, num;
while(rMin <= rMax) //二分法
{
rTmp = (rMax + rMin) / 2;
num = strToNum(a, rTmp);
if(num == -1 || num > t)
rMax = rTmp - 1;
else if(num < t)
rMin = rTmp + 1;
else if(num == t)
break;
}
if(num == t)
printf("%lld", rTmp);
else
printf("Impossible");
}
int main()
{
long long rMax, rMin, t;
char n1[11] = {'\0'}, n2[11] = {'\0'};
int tag, radix;
scanf("%s %s %d %d", n1, n2, &tag, &radix);
if(tag == 1)
{
t = strToNum(n1, radix); //已知的数
rMax = t + 1; //保存最大进制数
rMin = minRadix(n2);
judge(n2, rMax, rMin, t);
}
else
{
t = strToNum(n2, radix);
rMax = t + 1;
rMin = minRadix(n1);
judge(n1, rMax, rMin, t);
}
return 0;
}