原题
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
题目翻译
给定一对正整数,例如 6 和 110,这个等式 6 = 110 是真的吗?如果 6 是十进制数,110 是二进制数的话,答案是肯定的。
现在,给定一个正整数数对 N1,N2,并给出其中一个数字的进制,请你求出另一个数字在什么进制下,两数相等成立。
输入规范:
每个输入文件包含一个测试用例。每个案例占一行,包含 4 个正整数:
N1 N2 tag radix
N1 和 N2 是两个不超过10位的数字,radix
是其中一个数字的进制,如果 tag
为 1,则 radix
是 N1的进制,如果 tag
为2,则 radix
是 N2的进制。
注意,一个数字的各个位上的数都不会超过它的进制,我们用 0∼9 表示数字0∼9,用 a∼z表示 10∼35。
解题思路
这道题是前10题算偏难的题,本来想遍历radix所有的值来求解,但是测试点7总是不过,预计测试点7的radix超过1e6,若暴力求解会超时。
想了想发现两位及以上的数字都满足一个条件:进制越大,转换为10进制下的值就越大,联想到用二分来写。
代码(c++)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
string n1, n2;
int tag, radix;
LL nn1;
int get(char c){ // 0-9返回1-9,a-z返回10-35
if('0' <= c && c <= '9') return c - '0';
else return c - 'a' + 10;
}
LL fun(string x, int radix){ // 将radix进制的x转换为10进制
LL res = 0;
double p = 1;
for(int i = x.size() - 1; i >= 0; i--){
int t = get(x[i]);
if((double)res + t * p > 1e18) return 1e18; // 说明数很大,一定大于nn1了,用double因为发现LL也存不下
res += t * p;
p *= radix;
}
return res;
}
int main(){
cin >> n1 >> n2 >> tag >> radix;
if(tag == 2) swap(n1, n2); // 一直让n1作为已知进制的数
nn1 = fun(n1, radix);
LL l = 2, r = nn1;
for(auto c : n2) l = max(l,(LL)get(c) + 1); // 确定最小进制
while(l < r){ // 二分
LL mid = (l + r) >> 1;
if(fun(n2, mid) >= nn1) r = mid;
else l = mid + 1;
}
if(fun(n2, l) == nn1) cout << l;
else cout << "Impossible";
return 0;
}