PAT甲级刷题记录——1010 Radix (25分)

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 N​1​​ and N​2​​ , 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 N1and N2each 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-zrepresent the decimal numbers 10-35. The last number radixis the radix of N1if tagis 1, or of N2if tagis 2.

Output Specification:

For each test case, print in one line the radix of the other number so that the equation N1= N2is 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进制大小
  • 还有一个容易忽视的点,对于整型最好不要用里的pow()函数,因为那个的返回值是浮点型,如果强制转换成整型,会有精度上的错误,因此,要是碰到整型的乘方问题的话,最好是自己写一个返回值是整型的函数。

综上所述,如果对溢出的东西考虑的足够清楚的话,这题就能AC啦~

另外,【提醒一下自己】:一定要好好复习二分的写法,不要偷懒想着用STL的binary_search()了……虽然那个是现成的,但是返回值只能是bool类型,并不能返回具体想要的下标值……如果非要用的话,还是用lower_bound()好了,如果存在等于val的值,也是能找到那个值的位置的(但是这题不行哈,因为我们查找的值是一个10进制数,而搜索的范围是所有进制,除非预处理好所有进制对应的10进制数??hhh那未免也太大了)。

代码

#include
#include
#include
#include
#include
#include
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;
}

你可能感兴趣的:(PAT甲级)