PAT甲题题解-1010. Radix (25)-二分搜索

时间:2022-01-31 04:52:47

题意:给出n1和n2,以及其中一个数的进制,问另一个数是多少进制的情况下,才会是两个数相等。不存在的话,则输出Impossible

这题思路很简单,但是要考虑的比较多,在简单题里面算是比较好的。

有两个注意点
1.我被题目给骗了!!!以为最大进制只可能是36,所以在程序里就枚举2~36的进制,导致错了一大片样例
最小进制下界low当然是n2的最大数字位+1
最大进制上界high题目没有给出说明,但最大只可能为n1(前提n1>=low)。
为啥不会超过n1呢,比如
40 10 1 10
很明显10是进制表示除“个位”外最小的了,那么只有当进制为40时,它才等于n1,如果进制再大,就肯定大于n1了。

2.如果从low枚举到high,当high很大的时候,会很费时间,题目也设了一个样例会让你超时。
所以这里需要二分搜索二进制k

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
using namespace std;
char n1[],n2[];
int t,r;
long long tmp; /*
val2为n2在k进制下的值
val2<target,return -1
val2==target,return 0
val2>target,return 1
*/
int cmp(long long*a,long long k,long long target,int len){
long long val2=;
for(int i=;i<len;i++)
val2=val2*k+a[i];
//val2可能存在溢出的问题,这里要注意。
if(val2< || val2>target)
return ;
if(val2<target)
return -;
if(val2==target)
return ;
}
//二分搜索进制k
long long binarySearch(long long *a,long long low,long long high,long long target,int len){
long long l=low,r=high;
long long mid;
while(l<=r){
mid=(l+r)/;
if(cmp(a,mid,target,len)==)
return mid;
if(cmp(a,mid,target,len)<){
l=mid+;
}
else{
r=mid-;
}
}
return -; //impossible
}
int main()
{
scanf("%s %s %d %d",n1,n2,&t,&r);
if(t==){
swap(n1,n2); //交换一下,方便后面处理
}
char num[];
strcpy(num,n1);
int len=strlen(num);
long long val1=; //转化成十进制
for(int i=;i<len;i++){
if(''<=num[i] && num[i]<='')
tmp=num[i]-'';
else if('a'<=num[i] && num[i]<='z')
tmp=num[i]-'a'+;
val1=val1*r+tmp;
}
strcpy(num,n2);
len=strlen(num);
long long low=;
long long a[]; //将n2的字符表示转化成数组存储
for(int i=;i<len;i++){
if(''<=num[i] && num[i]<='')
tmp=num[i]-'';
else if('a'<=num[i] && num[i]<='z')
tmp=num[i]-'a'+;
a[i]=tmp;
if(tmp>low)
low=tmp;
}
low=low+;
long long high=max(low,val1)+;
long long ans=binarySearch(a,low,high,val1,len);
if(ans==-)
printf("Impossible\n");
else
printf("%lld\n",ans);
return ;
}