1010 Radix (25 分)
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
代码流程:
①init() 初始化Map,使Map[c]即为字符c表示的数字
②convertNum10(N1,radix,inf) 将N1转换为十进制数,若溢出(<0)则为-1
③low 二分下界是N2最大数字+1,因为只有这样才可以表示N2的最大数字
high 二分下界是max(low,t)+1,此时N2即使是个位数也能表示出N1,但不能更大,因为题目是求最小radix
④binarySearch(N2,low,high,t) 二分查找mid,其中注意N2转换为十进制溢出时等价于N2较大
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
LL Map[256]; //Map[c]直接取得c字符表达的数字
LL inf=(1LL << 63)-1; //移位表达式,2^63-1
void init(){
for(char c='0';c<='9';c++){
Map[c]=c-'0';
}
for(char c='a';c<='z';c++){
Map[c]=c-'a'+10;
}
}
//将a转换为十进制,t为上界
LL convertNum10(char a[],LL radix,LL t){
LL ans=0;
int len=strlen(a);
for(int i=0;i<len;i++){
ans=ans*radix+Map[a[i]]; //进制转换
if(ans<0 || ans>t) //ans<0说明LL溢出,ans>t说明超出上界(即N1的十进制)
return -1;
}
return ans;
}
//比较N1与t的大小,t是N1的十进制数
int cmp(char N2[],LL radix,LL t){
int len=strlen(N2);
LL num=convertNum10(N2,radix,t);
if(num<0)
return 1; //N2溢出说明N2>N1
if(num<t)
return -1; //N1比较大,返回-1
else if(t==num)
return 0; //相等返回0
else
return 1; //N2比较大,返回1
}
LL binarySearch(char N2[],LL left,LL right,LL t){
LL mid;
while(left<=right){ //因为这里是具体查找某个radix了,不是第一个之类的,用<=
mid=(left+right)/2;
int flag=cmp(N2,mid,t);
if(flag==0)
return mid;
else if(flag==-1)
left=mid+1;
else
right=mid-1;
}
return -1;
}
//找到N2中最大的数字
int findLargestDigit(char N2[]){
int ans=-1,len=strlen(N2);
for(int i=0;i<len;i++){
if(Map[N2[i]]>ans){
ans=Map[N2[i]];
}
}
return ans+1;
}
char N1[20],N2[20],temp[20];
int tag,radix;
int main(){
init();
scanf("%s %s %d %d",N1,N2,&tag,&radix);
if(tag==2){
strcpy(temp,N1);
strcpy(N1,N2);
strcpy(N2,temp);
}
LL t=convertNum10(N1,radix,inf); //将N1从radix进制转换为10进制
LL low=findLargestDigit(N2); //N2radix的下界,是最大的数字+1
LL high=max(low,t)+1; //上界
LL ans=binarySearch(N2,low,high,t); //二分
if(ans==-1)
cout << "Impossible";
else
cout << ans;
}