- 简单计算一下就可以发现,数据肯定要用long long存储
- 未知进制数的最小进制取决于出现过的最大位
- 未知进制数的最大进制却不是36!!!而是确定进制数(num1)转换为十进制后的结果,毕竟X进制的数不一定出现值为X-1的位
- 结果存在单调性,即进制越大,转换得到的结果越大,所以可以用二分来降低时间复杂度
- 二分查找过程中若num2 > num1 || num2 < 0,都作为进制取值过大的条件(num2<0说明进制太大,导致溢出成为负数)
从前辈的blog上找到了一个超强的样例
能过这个样例就可以A了这道题
Input:
s9jix hj 1 36
Output:
2792614
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
char A[15], B[15];
LL a[15], b[15];
int len1, len2, opt;
LL radix;
LL num1;
int init(char* str,LL num[15]) {
int len = strlen(str);
//1最低位 ~ n最高位
for (int i = 0; i < len; ++i) {
if (str[i] >= '0' && str[i] <= '9')
num[len - i] = (LL)str[i] - '0';
else num[len - i] = (LL)str[i] - 'a' + 10;
}
return len;
}
LL changeToDec(LL num[15],int len,LL rx) {
LL ans = 0;
LL o = 1;
for (int i = 1; i <= len; ++i) {
ans = ans + num[i] * o;
o = o * rx;
}
return ans;
}
LL findRadix(LL l, LL r) {
while (l <= r) {
LL m = (l + r) / 2;
LL num2 = changeToDec(b, len2, m);
if (num2 == num1)
return m;
else if (num2 > num1 || num2 < 0)
r = m - 1;
else l = m + 1;
}
return -1;
}
int main()
{
scanf("%s%s%d%lld",&A,&B,&opt,&radix);
//a数组存储已知进制的数
if (opt == 1) {
len1 = init(A, a);
len2 = init(B, b);
}
else {
len1 = init(B, a);
len2 = init(A, b);
}
//转换为十进制
num1 = changeToDec(a, len1, radix);
//b数组中出现的最小的数决定了进制下限
LL mx = 0;
for (int i = 1; i <= len2; ++i)
mx = max(mx, b[i]);
LL ans = findRadix(mx + 1, max(num1,mx + 1));
if (ans != -1) printf("%lld", ans);
else printf("Impossible");
return 0;
}