1010 Radix (25分)
题目
字符串形式给出两个数 n1, n2,告诉其中一个数的进制 radix,要使两个数相等,求另外一个数的进制的最小取值,如果无法满足输出 “Impossible”。
分析
进制越大,数值越大,对于另外一个数二分找进制即可。
上界,给出进制数 n1 的数值;下界,n2 中出现的最大的数 + 1。
特殊情况,两个数为 0 0,输出 1。注意二分时 long long 越界情况。
#include <bits/stdc++.h>
using namespace std;
#define d(x) cout<<x<<endl
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
char n1[20], n2[20];
ll tag, radix;
ll cal(char *arr, int len, ll radix) { // 求当进制为 radix 时,数组 arr 的值
ll res = 0;
for (int i = 0; i < len; i++) {
ll c = arr[i] > '9' ? arr[i] - 'a' + 10 : arr[i] - '0';
res = res * radix + c;
}
return res;
}
int main() {
scanf("%s%s%lld%lld", n1, n2, &tag, &radix);
if (tag == 2) swap(n1, n2);
int s1 = strlen(n1); int s2 = strlen(n2);
ll num = cal(n1, s1, radix); // 先求出 n1 的值
ll maxn = 0;
for (int i = 0; i < s2; i++) {
ll c = n2[i] > '9' ? n2[i] - 'a' + 10 : n2[i] - '0';
maxn = max(maxn, c);
}
ll l = maxn + 1, r = num + 1;
while (l <= r) {
ll mid = l + r >> 1, tmp = cal(n2, s2, mid);
if (tmp == num) {
printf("%lld\n", mid); return 0;
} else if (tmp > num || tmp < 0) { // 注意处理越界
r = mid - 1;
} else {
l = mid + 1;
}
}
printf("Impossible\n");
return 0;
}