pat甲级1010. Radix (25)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/richenyunqi/article/details/79536497

欢迎访问我的pat甲级题解目录哦https://blog.csdn.net/richenyunqi/article/details/79958195

1010. Radix (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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

题意分析:

这道题比较难,坑也很多。题意不难理解,给出两个进制数,并指定其中一个数的进制,要求求出另一个数的进制,使得这两个数相等。如果求出的进制不唯一,输出最小的那个进制

算法设计:

既然要比较两个不同进制数是否相等,最直接的方法当然是统一转换成10进制数再进行比较。既然要查找符合条件的进制,需要为这一进制指定一个查找范围:假设要查找进制的数为110,则查找范围的下限必然为2,因为110这个数中每一位的数字都应该小于它的进制;假设已经指定进制的数为61,进制为10,则查找范围的上限应该是62。也就是说,查找范围的下限应该是要查找进制的那个数最大的一位数字+1,上限应该是指定进制的数所代表的10进制数+1 。为了降低时间复杂度,可以用二分查找的方法,在查找范围内查找到第一个使得要查找进制的数在该进制下所代表的10进制数大于等于指定进制的数所代表的10进制数,如果能查找到并且在该进制下两数相等,则输出该进制,否则输出Impossible

注意点:

(1)使用二分查找,暴力查找会超时

(2)用long long储存,因为给定的数最多有10位,在大一点的进制下很容易超出int储存范围

c++代码:

#include<bits/stdc++.h>
using namespace std;
unordered_map<char,int>charToint;//记录0-9,a-z字符对应的进制
long long trans(char*s,long long radix){//转换成10进制
    long long result=0;
    for(int i=0;s[i]!='\0';++i)
        result=result*radix+charToint[s[i]];
    return result;
}
long long findRadix(char*n1,char*n2,long long radix){//查找符合要求的进制
    long long right=trans(n1,radix),left=-1,tag=right;//left指示要查找的进制数的下限,right指示要查找的进制数的上限,tag表示n1表示的十进制数
    for(int i=0;n2[i]!='\0';++i)//找到要查找的进制数的下限
        left=max(left,(long long)charToint[n2[i]]+1);
    while(left<right){//二分查找第一个使得n2指向的字符串表示的数大于等于tag的进制
        long long mid=left+(right-left)/2,k=trans(n2,mid);
        if(k<0||k>=tag)//k<0时表示数据已经超出long long存储范围
            right=mid;
        else if(k<tag)
            left=mid+1;
    }
    if(trans(n2,left)!=tag)//如果查找到的进制下两数不相等,返回-1
        left=-1;
    return left;
}
int main(){
    char s1[11],s2[11];
    long long tag,radix;
    scanf("%s %s%lld%lld",s1,s2,&tag,&radix);
    for(int i=0;i<36;++i)//将0-9,a-z字符对应的进制压入charToint的map中,方便进行转换
        charToint.insert({i<10?i+'0':i-10+'a',i});
    radix=tag==1?findRadix(s1,s2,radix):findRadix(s2,s1,radix);//查找符合条件的进制
    if(radix==-1)//没有找到输出Impossible
        printf("Impossible");
    else//否则直接输出
        printf("%lld",radix);
    return 0;
}
阅读更多

扫码向博主提问

日沉云起

用最短的代码,写最快的算法
  • 擅长领域:
  • 算法
去开通我的Chat快问
换一批

没有更多推荐了,返回首页