PAT-ADVANCED1010——Radix

我的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++解题报告:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值