思路
把已知进制的字符串转换为十进制数N1
。
对另一个字符串str
用二分法进行十进制数转换,初始二分区间为(m,h)
;其中m
为最低进制:通过遍历str
找到最大字符, 则进制为对应字符转换为数字+1;h
为m
与N1
中较大者。
注意点
此题数的范围较大,采用long long
类型
转换为10进制数时可能溢出, 当溢出时, 返回-1;
在二分过程中, 若某进制发生溢出, 则表明该进制下str转换成十进制数肯定大于N1
, 故应减小进制,对应二分区间右边界更新为 right = mid -1
;
AC代码
//2020.6.20
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
typedef long long LL;
LL inf = (1LL<<63)-1;
string str, temp1, temp2;
int tag;
LL r, N1 = 0, m;
LL max(LL a, LL b){
return a>b ? a: b;
}
LL change(string s, LL radix){ // 把str看成radix进制的数, 再转换为10进制
LL x, N = 0;
for(int i=0; i<s.size(); i++){
if(s[i]>='0' && s[i]<='9'){
x = s[i] - '0';
}
else{
x = s[i] - 'a' + 10;
}
N = N*radix + x;
if(N > inf || N<-1) return -1;
}
return N;
}
void init(){
string s;
if(tag == 1){
str = temp2;
s = temp1;
}
else{
str = temp1;
s = temp2;
}
N1 = change(s, r);
char cc = '0';
for(int i=0; i<str.size(); i++){
if(str[i]>cc){
cc = str[i];
}
}
if(cc>='0'&&cc<='9'){
m = (LL)(cc - '0') + 1;
}
else{
m = (LL)(cc - 'a' + 10) + 1;
}
}
LL binary(LL left , LL right){
LL mid;
while(left <= right){
mid = (left + right) / 2;
LL x = change(str, mid);
if(x == N1){
return mid;
}
else if(x == -1 || x > N1){
right = mid - 1;
}
else{
left = mid + 1;
}
}
return 0;
}
int main()
{
cin>>temp1>>temp2>>tag>>r;
init();
LL h = max(m, N1);
LL ans = binary(m,h);
if(ans != 0){
printf("%lld",ans );
}
else{
printf("Impossible");
}
return 0;
}