最开始想直接暴力,后来看网上题解说可以二分。
二分思路就是先将n1转化为10进制,二分搜索枚举n2的进制(low为n2的进制,hi为n1的10进制加1),将n2按照枚举的进制转换为10进制然后与n1的十进制进行比较。注意这里的二分是搜索最小的结果,因此第一次相等后仍然要向前面区间搜索看是否有更小的解。
坑点:
1、long long也可能会溢出,需要判断溢出
2、每一步二分的结果需要判断是否为符合条件
代码
:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
LL getDecimal(string s,int radix){
LL ans = 0;
if(radix == 10){
for(int j=0;j<s.length();j++)
ans = ans*10+(s[j]-'0');
}else{
LL time = 0;
LL base = 0;
LL mul = 1;
for(int j=s.length()-1;j>=0;j--){
//基数
if(s[j]>='0'&&s[j]<='9')
base = s[j]-'0';
else if(s[j]>='a'&&s[j]<='z')
base = s[j]-87;
if(time == 0)
mul = 1;
else{
mul = 1;
for(int i=0;i<time;i++)
mul = mul*radix;
}
//cout<<"*"<<base<<" "<<mul<<" "<<time<<endl;
time++;
if(base < 0) //溢出
return -1;
ans = ans + base*mul;
if(ans<0) //溢出
return -1;
}
}
return ans;
}
LL getLow(string s1){
LL mmax = -1;
for(int i=0; i < s1.length(); i++){
if(s1[i]>='0'&&s1[i]<='9')
if(mmax < s1[i]-'0')
mmax = s1[i]-'0';
else if(s1[i]>='a'&&s1[i]<='z')
if(mmax < s1[i]-87)
mmax = s1[i]-87;
}
return mmax;
}
int main()
{
string n1,n2;
LL flag,radix;
cin>>n1>>n2>>flag>>radix;
if(flag == 2)
swap(n1,n2);
LL cmp = getDecimal(n1,radix);
LL hi = cmp+1;
LL low = getLow(n2)+1;
LL mid = 0;
LL temp = 0;
LL res = 0;
bool flag2 = false;
while(low <= hi){
mid = low+(hi-low)/2; //防止溢出
temp = getDecimal(n2,mid);
//cout<<temp<<" "<<cmp<<endl;
if(temp == cmp){ //证明有结果并将结果记录。万一前面没有结果则输出res
//cout<<temp<<" "<<cmp<<" "<<mid<<endl;
flag2 = true;
res = mid;
}
if(temp >= cmp || temp == -1) //判断溢出
hi = mid - 1;
else if(temp < cmp)
low = mid + 1;
}
if(flag2)
cout<<res<<endl;
else
cout<<"Impossible"<<endl;
return 0;
}