PAT A1010 Radix +神

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 N​1​​ and N​2​​, 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;
}

猜你喜欢

转载自blog.csdn.net/qq_36525099/article/details/87924702
今日推荐