我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536
题目描述:
题目翻译:
1010 进制
给定一对正整数,例如6和110,等式6 = 110可能是真的吗?如果6是十进制数,110是二进制数,那就是真的。
任意给出一对正整数N1和N2,你的任务是根据一个数的进制找出另一个数的进制,使得N1 = N2成立。
输入格式:
每个输入文件包含一个测试用例。每个测试用例在一行中有4个正整数:
N1 N2 tag radix
N1和N2均不超过10位数。每位数都比其进制要小,其中0-9由数字0-9表示,而10-35由小写字母a-z表示。如果tag是1,则radix指的是N1的进制。如果tag是2,则radix指的是N2的进制。
输出格式:
对每个测试用例,如果能找到一个进制使得N1 = N2,则输出这个进制。如果不可能,则输出Impossible。如果答案不唯一,则输出最小的那个进制。
输入样例1:
6 110 1 10
输出样例1:
2
输入样例2:
1 ab 1 2
输出样例2:
Impossible
知识点:二分查找法
思路:将N1和N2均转换成10进制比较
(1)将已经确定进制的数放在N1,将未确定进制的数放在N2。
(2)将N1转换为10进制数,使用long long类型进行存储(由于题目给定的数据中,可能有10个数位,36进制,因此结果会超过int,但不会超过long long)。
(3)测试数据默认保证已知进制的那个数在转换成10进制时不超过long long。但是对未知进制的数在转换成10进制时需要判断是否溢出(只要在转换过程中某步小于0即为溢出)。
(4)对于未知数的进制下限,我们很容易根据N2中含有的字符确定。而其上界则应该是N1转换成的10进制数。因为对于更大的进制来说,其对于N2的表示都是一样的,我们不予考虑。
时间复杂度是O(nlogn),其中n是未知数的进制的上限和下限差。
C++代码:
#include<iostream>
#include<string>
using namespace std;
string N1, N2;
int tag, radix;
int main() {
cin >> N1 >> N2 >> tag >> radix;
//如果tag为2,则交换N1和N2的值
if(tag == 2) {
string temp = N1;
N1 = N2;
N2 = temp;
}
//将N1转换为10进制数据(题目测试用例保证该10进制数在long long范围内)
long long num1 = 0;
for(int i = 0; i < N1.length(); i++) {
if(N1[i] >= 'a' && N1[i] <= 'z') {
num1 = num1 * radix + N1[i] - 'a' + 10;
} else {
num1 = num1 * radix + N1[i] - '0';
}
}
//left定义为N2的最小进制
long long left = -1;
for(int i = 0; i < N2.length(); i++) {
if(N2[i] >= 'a' && N2[i] <= 'z') {
if(N2[i] - 'a' + 10 > left - 1) {
left = N2[i] - 'a' + 10 + 1;
}
} else {
if(N2[i] - '0' > left - 1) {
left = N2[i] - '0' + 1;
}
}
}
//right定义为N2的最大进制
long long right = max(left, num1 + 1);
while(left <= right) {
long long mid = left + (right - left) / 2;
long long num2 = 0;
for(int i = 0; i < N2.length(); i++) {
if(N2[i] >= 'a' && N2[i] <= 'z') {
num2 = num2 * mid + N2[i] - 'a' + 10;
} else {
num2 = num2 * mid + N2[i] - '0';
}
}
if(num1 == num2) {
printf("%lld\n", mid);
break;
} else if(num2 < 0) { //如果num2超过了long long的范围,肯定比num1要大
right = mid - 1;
} else if(num1 < num2) {
right = mid - 1;
} else {
left = mid + 1;
}
}
if(left > right) {
printf("Impossible\n");
}
return 0;
}
C++解题报告: