1010 Radix (25 point(s))
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
啊呦,这道题目好难哟,做了好久才通过,怎么说呢,这道题看似好像不难,可是后面发现好多易错的坑哟。
先讲题目内容,就是N1,N2为两个数字,radix为进制,tag=1意味着第一个数字的进制为radix,若tag==2,则意味着第二个数字的进制为radix。给出两个数字,以及其中一个数的进制,求第二个数字的进制,以满足两个数数值相同(若答案不唯一,取最小的,这里满足不唯一的情况大概就是只有一位数的时候出现的情况)。
思路,1、确定已知的进制是哪一个数字,调整顺序,使得已知的数放在前面(为了方便),
2、将已知条件的数转为10进制。
3、利用二分法,求出满足条件的进制
注意点 1、题中给出的是0~9 a~z,但不是意味着进制范围最大是36啊,上限无限大啊!!!!!!好坑哟
2、细细分析,我们在使用二分法时候,最开始取下限为每一位数的最大值+1,且该数字要大于等于2,上限为(下限和已知数字十进制的最大值)+1。
3、关于范围问题,题目没有具体限定范围,因此未知是否化为10进制的时候会溢出。这是个问题,我看《算法笔记》书上,它是默认已知数化位10进制时不会超过longlong范围(这个我也不知道怎么得的),但是未知数字在转化为10进制的时候,可能会超出longlong范围!!!这个很关键,搞了半天才晓得。所以在转化的某一步骤中,突然变为负数,说明溢出了。
代码如下
#include <cstdio>
#include <cstring>
typedef long long LL;
//数字以字符数组的形式保存,将进制为radix的数转换为10进制返回,
LL GetResult(char a[],LL radix)
{
LL result=0,cheng=1;
int i;
i=strlen(a)-1;
while(i>=0)
{
if(a[i]<'0'||a[i]>'9')
result+=(a[i]-'a'+10)*cheng;
else
result+=(a[i]-'0')*cheng;
if(result<0)
return -1;
cheng*=radix;
i--;
}
return result;
}
//获取数值最大的位数,返回
int findMax(char a[])
{
int max=0,temp;
int i=strlen(a)-1;
while(i>=0)
{
if(a[i]<'0'||a[i]>'9')
temp=(a[i]-'a')+10;
else
temp=a[i]-'0';
if(temp>max)
max=temp;
i--;
}
return max+1;
}
int main()
{
char n1[11],n2[11],n[11];
LL result=0,result_temp;
int tag,radix;
LL left=2,right,mid;
scanf("%s%s%d%d",n1,n2,&tag,&radix);
if(tag==2) //交换n1和n2内容
{
strcpy(n,n1);
strcpy(n1,n2);
strcpy(n2,n);
}
result=GetResult(n1,radix);
left=findMax(n2);
if(left<2)
left=2;
right= (left>result)?left+1:result+1;
while(left<=right)
{
mid=(left+right)/2;
result_temp=GetResult(n2,mid);
if(result<result_temp || result_temp <0) //包含溢出判断,溢出说明太大了
right=mid-1;
else if(result==result_temp)
{
printf("%d",mid);
return 0;
}
else
left=mid+1;
}
printf("Impossible");
}
在看书以及百度别人的写法时候,发现自己的编码习惯和别人差别还挺大的,还有很多要改善的。