Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is yes
, if 6 is a decimal number and 110 is a binary number.
Now for any pair of positive integers N1 and N2, your task is to find the radix of one number while that of the other is given.
Input Specification:
Each input file contains one test case. Each case occupies a line which contains 4 positive integers:
N1 N2 tag radix
Here N1
and N2
each has no more than 10 digits. A digit is less than its radix and is chosen from the set { 0-9, a
-z
} where 0-9 represent the decimal numbers 0-9, and a
-z
represent the decimal numbers 10-35. The last number radix
is the radix of N1
if tag
is 1, or of N2
if tag
is 2.
Output Specification:
For each test case, print in one line the radix of the other number so that the equation N1
= N2
is true. If the equation is impossible, print Impossible
. If the solution is not unique, output the smallest possible radix.
Sample Input 1:
6 110 1 10
Sample Output 1:
2
Sample Input 2:
1 ab 1 2
Sample Output 2:
Impossible
题目大意
这题给出n1、n2两个数字(进制/基数可能不同),同时给出一个tag和radix,tag为1表明radix是n1的基数,tag为2表明radix是n2的基数,假设n1和n2的值相等,求出此时另外一个数的基数。
个人思路
(为了阐述方便这里假设tag为1。)这题的大致思路是先将n1转换为十进制,然后使用二分法寻找n2的基数,使得在n2的基数下n2的十进制数值等于n1的十进制数值。
难点有这么几个:
- 首先是要确定n2的基数寻找范围(即二分法的查找范围,这里参考了柳神的写法,如果没考虑好这点第7个测试点过不去)。
- 寻找下限:对于n2来说,进制最小值要比每位的最小值大,例如n2中不同位上最小的值为3,那么最小也得是4进制。
- 寻找上线:上限为n1的十进制数值和下限中的较大值。因为要寻找n1的值等于n2的值的进制,如果n2的进制比数值本身还大那就只有1位了,除非下限比数值大,因为数值比下限小是不允许的。
- 在将n2转化为十进制数值时,最多有10位,如果基数很大就算是long long也会溢出,溢出后数值会变成负数(因为补码存储数字,溢出后首位即符号位变成1了),所以如果将n2转化为基数后为负数说明mid太大了。
- 如果有多个答案,输出满足条件的最小值。因此要二分法要找到从小到大满足条件的第一个基数。
实现代码
#include <cstdio>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
// 将字符串数字转换成对应进制的十进制数值
ll digit2decimal(string nums, ll radix) {
ll ret = 0;
for (int i = 0; i < nums.length(); i ++) {
int tmp = 0;
if (nums[i] >= '0' && nums[i] <= '9') tmp = nums[i]-'0';
else if (nums[i] >= 'a' && nums[i] <= 'z') tmp = 10+nums[i]-'a';
ret = ret*radix + tmp;
}
return ret;
}
// 二分法寻找满足条件的进制,如果不存在返回-1
ll binary_search(string n, ll value) {
// 寻找下限和上线的写法参考了柳神的写法
char it = *max_element(n.begin(), n.end());
ll left = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;
ll right = max(value, left);
while (left < right) {
ll mid = (left+right) / 2;
ll v = digit2decimal(n, mid);
if (v < 0) right = mid - 1;
else if (v >= value) right = mid;
else left = mid + 1;
}
if (digit2decimal(n, left) == value) return left;
return -1;
}
int main() {
string n1, n2;
int tag, radix;
cin >> n1 >> n2 >> tag >> radix;
ll value;
ll ans = -1;
if (tag == 1) {
value = digit2decimal(n1, radix);
ans = binary_search(n2, value);
}
else if (tag == 2) {
value = digit2decimal(n2, radix);
ans = binary_search(n1, value);
}
if (ans == -1) cout << "Impossible";
else cout << ans;
return 0;
}
总结
学习不息,继续加油