[PAT甲级]1010. Radix (25)(求另一个数的基数)

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 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,N1和N2是正整数,如果tag==1,N1就是radix进制数,如果tag==2,N1就是radix进制数,求出另一个数的进制

思路:

  • 先将给出进制的数转化为十进制数
  • 再求出另一个数的进制上限和下限
  • 最后用二分法求出另一个数的进制

格外注意:

  • 这道题困扰我好久,说几点注意的
  • 首先是进制的上下限,下限就是另一个数的最大字符+1,上限本应是N1(给出进制的数),但是给出一个反例 11 b 1 10,如果b的上限是11(即N1)的话,结果就错了,所以上限应该是 N1 和 另一个数的最大字符 中较大的一个+1,可能有点儿绕口,请仔细品读
  • 其次题目没有给定N1 N2范围,最好使用long long int
  • 第三也是最重要的一点,未知进制转化为十进制数的时候可能会溢出,如果溢出了,那么该十进制是小于0的,对于小于0的数字,要及时更改进制上限
  • 第四,这个博客说只有一位数时候可能出现多个解,其余情况均只有一个解,那其实不用数组ans存储也是可以的

代码:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
map<char, int> Map;//各个字符对应一个数字
string n1,n2;
int tag, radix;
vector<long long> ans;//存储符合要求的进制
long long toTen(string s, long long radix){//将radix进制转化为10进制数
    long long res = 0;
    for(int i=0; ireturn res;
}
long long findLow(string s){//找出另一个数的基数下限
    long long res = -1;
    for(int i=0; iif(Map[s[i]] > res)
            res = Map[s[i]];
    }
    return res+1;
}
int cmp(string n2, long long radix, long long t){//判断基数是否符合条件
    long long num = toTen(n2, radix);
    if(num < 0)//很重要,注意事项第三点
        return 1;
    if(num < t)//基数偏小
        return -1;
    else if (num > t)//基数偏大
        return 1;
    else
        return 0;//基数符合条件
}
long long binarySearch(string n2, long long left, long long right,long long t){//二分查找寻找符合条件基数
    long long mid;
    while(left <= right){
        mid = (right+left)/2;
        int flag = cmp(n2, mid, t);//判断基数是否符合条件
        if(flag == 0){//将符合要求的进制存入数组中
            ans.push_back(mid);
            right = mid - 1;
        }else if(flag == 1)
            right = mid - 1;
        else
            left = mid + 1;
    }
    if(ans.size() == 0)
        return -1;
    sort(ans.begin(), ans.end());
    return ans[0];//返回符合要求最小进制
}
int main() {
    for(char c='0'; c<='9'; c++)
        Map[c] = c-'0';
    for(char c='a'; c<='z'; c++)
        Map[c] = c-'a'+10;
    cin >> n1 >> n2 >> tag >> radix;
    if(tag == 2){
        string temp = n1;
        n1 = n2;
        n2 = temp;
    }
    long long t = toTen(n1, radix);//将给出基数的数转化为十进制数
    long long low = findLow(n2);//找出另一个数的基数下限
    long long high = low>t ? low+1 : t+1;//找出另一个数的基数上限
    long long res = binarySearch(n2, low, high, t);//二分查找寻找符合条件基数
    if(res == -1)
        printf("Impossible");
    else
        printf("%lld", res);
    return 0;
}

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