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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
void str_to_vec(string str, vector<int>& vec) {
for (auto c : str) {
if (c >= '0' && c <= '9') vec.push_back(c - '0');
if (c >= 'a' && c <= 'z') vec.push_back(c - 'a' + 10);
}
}
LL to_value(LL radix, vector<int> vec) {
LL res = 0;
for (auto val : vec) {
if ((double)res * radix + val > 1e16) return 1e18;
res = res * radix + val;
}
return res;
}
int main() {
string N1, N2;
int tag, radix;
cin >> N1 >> N2 >> tag >> radix;
vector<int> base, test;
if (tag == 1) { str_to_vec(N1, base); str_to_vec(N2, test); }
if (tag == 2) { str_to_vec(N2, base); str_to_vec(N1, test); }
LL target = to_value(radix, base);
LL l = 0, r = max(target,36ll);
for(auto i : test) l = max(l, (LL)(i + 1));
while (l < r) {
LL mid = l + r >> 1;
if(to_value(mid, test) >= target) r = mid;
else l = mid + 1;
}
if (to_value(r, test) == target) cout << r;
else cout << "Impossible";
return 0;
}
总结
这题具有一定难度,主要核心是进制的转换与二分法的边界确定。
1. 首先读入数据,确定一个基准数据(已知进位和数值的数据),然后计算出其十进制数。这里用long long能解决问题的主要原因是该题数据最大估计为36^10(数值部分最多10位)小于1e18。
2. N进制转10进制,to_value采用的是秦九韶算法。这里尤其要注意为什么传入的参数数据类型为long long,因为对待定的进制数,其进制不确定,这里我们要分析进制数的进制取值范围。
首先,进制数如果是1位,那么即便取最大进制n,数值也只能表示0~n-1。
如果,进制数是2位,数值范围则是0~n*(n-1)。但由于目标target数值固定,对于待定test进制数,如果要与其相等,那么只能在进制长度与进制大小做取舍。比如(10)的b进制,其值为b,就等于target时,b就要取long long才能表示。
3. 二分法边界的确定
3.1 左边界:我们知道一个进制数的每一位最大值不超过进制,所以我们可以通过遍历进制数,来确定这个进制数的最小进制是多少,即左边界。这里的LL(i+1)要连着。
3.2 右边界:目标数与36ll取最大,至少大于等于36。
4. 二分法模型
a. l < r
b. mid = l + r >> 1 移位运算求中间值
c. mid靠右