PAT Advanced 1010 Radix(二分法)

題目描述

題目地址

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

基本思路

PAT題目都很迷,很多地方都不說清楚輸入範圍。。。

這道題輸入數據不會超過long long,所以可以放心的使用基本思路計算不同進制下的值

ll getRes(string &tar, int radix) {
    ll res = 0;
    int len = tar.length();
    for(int i = 0;i < tar.length();i++) {
        res = res*radix + getNum(tar[i]);
        if(res < 0) {
            return -1;
        }
    }
    return res;
}

如果每次都從進制2開始遞增進制,直到一種不可能的情況出現,但這種方法對大小差距極大的兩個數特別耗時,對於這種在一個序列中尋找一個正確解的過程,顯然是用二分法解決。

但是二分法需要一個範圍,那麼這道題的進制範圍是在哪一個範圍。首先對於R進制的串,對於數串內的數必須小於R,所以獲取此串的最小進制(下界)就顯而易見了

int getNum(char tar) {
    if(tar >= '0' && tar <= '9') {
        return tar - '0';
    }
    else {
        return tar - 'a' + 10;
    }
}

int getMinRadix(string &tar) {
    // 也可以使用C++的max_element函數
    char c = '0';
    for(int i = 0;i < tar.length();i++) {
        if(tar[i] > c) {
            c = tar[i];
        }
    }
    return  max(getNum(c) + 1, 2);
}

上界即爲max(minRadix, num) num爲已知進制的數的值,因爲題目中只涉及到0-35的值,所以num作爲上屆已經足夠,因爲個位是不可能達到num值的最高就是35,那麼在2位數字的情況下最小也是10,此時10在num進制下就是num,所以num進制的最小值就是num,在往上就會大於num就沒有必要了

所有在上下界進行二分法查找即可

代碼如下:

#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
//#define LOCAL

using namespace std;

typedef long long ll;

int getNum(char tar) {
    if(tar >= '0' && tar <= '9') {
        return tar - '0';
    }
    else {
        return tar - 'a' + 10;
    }
}

int getMinRadix(string &tar) {
    char c = '0';
    for(int i = 0;i < tar.length();i++) {
        if(tar[i] > c) {
            c = tar[i];
        }
    }
    return  max(getNum(c) + 1, 2);
}

ll getRes(string &tar, int radix) {
    ll res = 0;
    int len = tar.length();
    for(int i = 0;i < tar.length();i++) {
        res = res*radix + getNum(tar[i]);
        if(res < 0) {
            return -1;
        }
    }
    return res;
}

int main() {
#ifdef LOCAL
    freopen("./in.txt", "r", stdin);
#endif
    string A, B;
    int tag, radix;
    cin >> A >> B >> tag >> radix;
    if(tag == 2) {
        swap(A, B);
    }
    // B 是 要計算的
    ll tar = getRes(A, radix);
    //  二分
    ll left = getMinRadix(B);
    ll right = max(left, tar);
    while (left <= right) {
        ll mid = (left + right) >> 1;
        ll temp = getRes(B, mid);
        if(temp == tar) {
            printf("%lld", mid);
            return 0;
        }
        if(temp < 0 || temp > tar) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    printf("Impossible");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章