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
思路
这题只能说……真的有毒……修修补补终于AC了(泪目)……
题意理解起来还是很简单的,但是坑点巨多(划重点,巨多!!!)。题目大意就是给你两个数N1和N2,然后指定一个数的进制,让你计算,是否存在一个进制数,让另一个数和已知进制的数相等。
下面说一下这题的【坑点】:
- 必须要用二分搜索,我一开始没用二分搜索是20分,两个测试点直接超时,还有几个测试点是WA;
- 二分搜索的下界是未知进制数的数位最大的那个+1,上界是下界和已知进制数的十进制的较大者+1,而不是简单的[2, INT_MAX];
- 就像上面说到的,radix的范围最大可以到INT_MAX,即:231-1,因此,所有int型(除了在for循环里的)都应该改成long long型,此外,虽然已知进制数的那个数转换为10进制时,不会超过long long型范围,但是未知进制的那个数转换为10进制时,是有可能超过long long的范围的(因为我们要不断把它假设成某个进制转换成10进制后进行比较),因此,在二分查找的时候,还需要处理溢出的情况——转换为10进制之后若为负数,显然是过大的,需要往左子区间查找;
- 如果N1和N2两数相等,并不能直接输出题目给出的进制数radix,因为题目要求如果解不唯一,需要输出最小的radix,因此,干脆不要考虑这种特殊情况了,统统用二分就好了(比如输入:6 6 1 10,按题目意思应该输出7才对);
- 在对已知进制的数转化成10进制时,需要考虑是否转换的时候就已溢出,或者超过了long long的最大范围;
- 而在对未知进制的数转化成10进制时,除了需要考虑转换的时候是否已经溢出,还需要考虑是否超过了前者的10进制大小;
- 还有一个容易忽视的点,对于整型最好不要用<math.h>里的pow()函数,因为那个的返回值是浮点型,如果强制转换成整型,会有精度上的错误,因此,要是碰到整型的乘方问题的话,最好是自己写一个返回值是整型的函数。
综上所述,如果对溢出的东西考虑的足够清楚的话,这题就能AC啦~
另外,【提醒一下自己】:一定要好好复习二分的写法,不要偷懒想着用STL的binary_search()了……虽然那个是现成的,但是返回值只能是bool类型,并不能返回具体想要的下标值……如果非要用的话,还是用lower_bound()好了,如果存在等于val的值,也是能找到那个值的位置的(但是这题不行哈,因为我们查找的值是一个10进制数,而搜索的范围是所有进制,除非预处理好所有进制对应的10进制数??hhh那未免也太大了)。
代码
#include<cstdio>
#include<stdlib.h>
#include<algorithm>
#include<string>
#include<string.h>
#include<iostream>
using namespace std;
long long power(long long x, long long y){//x^y
long long ans = 1;
for(int i=0;i<y;i++){
ans *= x;
}
return ans;
}
const long long inf = power(2,63)-1;
long long RtoD(string x, long long R, long long t){//R进制->10进制
long long result = 0;
for(int i=x.length()-1, j=0;i>=0, j<x.length();i--, j++){
if(x[i]>='a'&&x[i]<='z') result += (x[i]-87)*power(R, j);
else result += (x[i]-'0')*power(R, j);
if(result<0||result>t) return -1;
}
return result;
}
long long binarySearch(long long left, long long right, long long x, long long tag, string N1, string N2){
long long mid;
while(left<=right){
mid = (left+right)/2;
if(tag==1){
if(RtoD(N2, mid, x)==x) return mid;
else if(RtoD(N2, mid, x)>x||RtoD(N2, mid, x)<0){
right = mid-1;
}
else{
left = mid+1;
}
}
else{
if(RtoD(N1, mid, x)==x) return mid;
else if(RtoD(N1, mid ,x)>x||RtoD(N1, mid, x)<0){
right = mid-1;
}
else{
left = mid+1;
}
}
}
return -1;
}
long long findLargestDigit(string x){
long long ans = -1;
for(int i=0;i<x.length();i++){
if(x[i]>='a'&&x[i]<='z'){
if(x[i]-87>ans) ans = x[i]-87;
}
else{
if(x[i]-'0'>ans) ans = x[i]-'0';
}
}
return ans+1;
}
int main()
{
string N1, N2;
long long tag, radix;
cin>>N1>>N2>>tag>>radix;
if(tag==1){
long long val = RtoD(N1, radix, inf);
long long low = findLargestDigit(N2);
long long high = max(low, val)+1;
long long result = binarySearch(low, high, val, tag, N1, N2);
if(result==-1) cout<<"Impossible";
else cout<<result;
}
else{
long long val = RtoD(N2, radix, inf);
long long low = findLargestDigit(N1);
long long high = max(low, val)+1;
long long result = binarySearch(low, high, val, tag, N1, N2);
if(result==-1) cout<<"Impossible";
else cout<<result;
}
return 0;
}