【PAT甲級】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
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,tag為1表明radix是n1的基數,tag為2表明radix是n2的基數,假設n1和n2的值相等,求出此時另外一個數的基數。
個人思路
(為了闡述方便這裡假設tag為1。)這題的大致思路是先將n1轉換為十進位制,然後使用二分法尋找n2的基數,使得在n2的基數下n2的十進位制數值等於n1的十進位制數值。
難點有這麼幾個:
- 首先是要確定n2的基數尋找範圍(即二分法的查詢範圍,這裡參考了柳神的寫法,如果沒考慮好這點第7個測試點過不去)。
- 尋找下限:對於n2來說,進位制最小值要比每位的最小值大,例如n2中不同位上最小的值為3,那麼最小也得是4進位制。
- 尋找上線:上限為n1的十進位制數值和下限中的較大值。因為要尋找n1的值等於n2的值的進位制,如果n2的進位制比數值本身還大那就只有1位了,除非下限比數值大,因為數值比下限小是不允許的。
- 在將n2轉化為十進位制數值時,最多有10位,如果基數很大就算是long long也會溢位,溢位後數值會變成負數(因為補碼儲存數字,溢位後首位即符號位變成1了),所以如果將n2轉化為基數後為負數說明mid太大了。
- 如果有多個答案,輸出滿足條件的最小值。因此要二分法要找到從小到大滿足條件的第一個基數。
實現程式碼
#include <cstdio>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
// 將字串數字轉換成對應進位制的十進位制數值
ll digit2decimal(string nums, ll radix) {
ll ret = 0;
for (int i = 0; i < nums.length(); i ++) {
int tmp = 0;
if (nums[i] >= '0' && nums[i] <= '9') tmp = nums[i]-'0';
else if (nums[i] >= 'a' && nums[i] <= 'z') tmp = 10+nums[i]-'a';
ret = ret*radix + tmp;
}
return ret;
}
// 二分法尋找滿足條件的進位制,如果不存在返回-1
ll binary_search(string n, ll value) {
// 尋找下限和上線的寫法參考了柳神的寫法
char it = *max_element(n.begin(), n.end());
ll left = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;
ll right = max(value, left);
while (left < right) {
ll mid = (left+right) / 2;
ll v = digit2decimal(n, mid);
if (v < 0) right = mid - 1;
else if (v >= value) right = mid;
else left = mid + 1;
}
if (digit2decimal(n, left) == value) return left;
return -1;
}
int main() {
string n1, n2;
int tag, radix;
cin >> n1 >> n2 >> tag >> radix;
ll value;
ll ans = -1;
if (tag == 1) {
value = digit2decimal(n1, radix);
ans = binary_search(n2, value);
}
else if (tag == 2) {
value = digit2decimal(n2, radix);
ans = binary_search(n1, value);
}
if (ans == -1) cout << "Impossible";
else cout << ans;
return 0;
}
總結
學習不息,繼續加油