此题难度较大,自己写了3次,在不借助外在帮忙的状况下最好问题才21分,对于第一次尝试的同学,能够临时放弃。

题目粗心:

输出四个整数N1、N2、tag、radix。其中tag--1示意N1为radix进制数,tag--2示意N2为radix进制数。范畴:N1和N2均不超过10个数位,且每个数位均为0-9或a~z,其中0~9示意数字0~9、a~z示意数字10-35.
求N1和N2中未知进制的那个数是否存在,并满足某个进制时和另一个数在十进制下相等的条件。若存在,则输入满足条件的最小进制:否则,输入Impossible.

算法思路:

此题的难点次要有2个,一个是N2进制数的范畴的确定,一个是在该范畴中搜寻的办法。咱们在这里假如将曾经晓得的进制数设定为N1,而后如果tag等于2,就让N1和N2进行替换

对于N2进制的范畴确定如下:

第一:对于其下界很显著为其数字中呈现的最大数字加1,比方123456789,这个数字起码是10进制的,因为呈现了9

第二:对于其上界的确定比拟没有那么让人容易想到,首先咱们晓得对于1位数字,其进制数和其转化为10进制数的大小没有任何关系所以其上界就是下界,其次,对于位数大于1的数字,想要求出最大的进制数,并且要转化为10进制数后和N1的十进制数相等,就必须得保障该数字最小,天然就能够发现位数大于2位的最小数字就是10,而想要该数字转化为10进制数后和N1的十进制数相等,那么N2的进制数必须为N1的10进制数,综上所述,N2进制数的上界为下界和N1的10进制数的最大值

对于在下界和上界之间搜寻N2进制的办法:

咱们晓得当一个数字的进制数被固定的时候,其十进制数会随着该数字的增大而增大,当其数字固定的时候,其十进制数会随着进制数的增大而增大.那么咱们为了在N2的下界和上界中搜寻出一个数字作为N2的进制数,使其转化为10进制数后和N1的十进制数相等,能够应用二分搜寻的办法查找该进制数.具体做法为咱们取得其区间中值mid,而后将N2转化为10进制数,如果该数字和N1的十进制数相等,输入mid并且返回,如果小于N1的十进制数,阐明以后的进制数较小,向右子区间搜寻,否则像左子区间搜寻。退出循环后阐明没有搜寻到符合条件的进制数,输入Impossible

留神点:

1、将N2转化为10进制数的时候有可能会溢出,必须得判断在进行区间的划分,然而N1不会溢出能够不必判断,测试点6,8,12,13,15,16考查N2溢出问题
2、有人可能会间接将区间设置为[0,2^63-1],然而理论测试后果是测试点0,1,11,18会谬误得21分(也算是个不错的分数了),如果下界设置为1更加会出错只能失去14分,自己也不晓得为什么。
3、题目所说的多个进制数中输入最小的进制数,个人感觉这个条件是没有用的,因为满足不存在数字肯定,进制数不同还能失去十进制数雷同的。
4、暴力搜寻会超时,此题基本上找到上下界,就能拿到20分左右。

提交后果:

AC代码:

#include <cstdio>#include <algorithm>#include <vector>#include <string>#include <iostream>using namespace std;// radix进制数num转化为10进制数long long toDecimal(string num, long long radix){    if(num=="0"){        return 0;    }    long long result = 0;    long long expo = 1;    for (int i = num.size()-1; i>=0 ; --i) {        if(num[i]>='0'&&num[i]<='9'){            result += (num[i]-'0')*expo;        } else if(num[i]>='a'&&num[i]<='z'){            result += (num[i]-'a'+10)*expo;        }        expo *= radix;    }    return result;}// 获取N2的最小进制数,为其呈现的最大数字加1long long getInfRadixOfN2(string N2){    int radix = -1;    for (int i = 0; i < N2.size(); ++i) {        int temp;        if(N2[i]>='0'&&N2[i]<='9'){            temp = N2[i]-'0';        } else if(N2[i]>='a'&&N2[i]<='z'){            temp = N2[i]-'a'+10;        }        if(temp>radix){            radix = temp;        }    }    return radix+1;}int main(){    string N1,N2;    cin>>N1>>N2;    int tag,radix;    // 这里保障radix为N1的,查找N2的进制数使其最靠近N1    scanf("%d %d",&tag,&radix);    if(tag==2){        // radix为N2的就替换N1和N2        swap(N1,N2);    }    long long decimalOfN1 = toDecimal(N1,radix);    long long decimalOfN2;    long long left=getInfRadixOfN2(N2);// 测试点0,6,19考查,left写成7测试点0和19会正确    long long right=max(left,decimalOfN1);    long long mid;    while (left<=right){        mid = left + (right-left)/2;        decimalOfN2 = toDecimal(N2,mid);        if(decimalOfN1==decimalOfN2){            printf("%lld",mid);            return 0;        } else if(decimalOfN2<decimalOfN1&&decimalOfN2>0){// 测试点6,8,12,13,15,16考查N2溢出问题            left = mid+1;        } else {            right = mid-1;        }    }    printf("Impossible");    return 0;}