PAT 甲级测试题目 -- 1010 Radix

题目链接

题目描述

给你两个数以及其中一个数的基数(进制数),找出另一个数的基数,找不到就输出 Impassible

分析

思路不是很难,基本可以用进制转换加循环判断做,但是有坑。。。
坑1:上界不是36.。。。上界是确定的那个数的十进制加 1 。
坑2:暴力循环会导致时间超限,用二分法解决
坑3:二分过程中会有数据溢出,得到的负数处理方式和找到较大数处理方式一样,因为溢出的数和题目条件不符,所以可以舍弃。

实现

#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;

// 用于判断进制数是否合理,顺便记录下未提供进制数据的进制数,用于优化查找基数次数。

// 任意进制转换为 10 进制
long long TransSystemToDec(char* number, double radix) {
	double times = strlen(number) - 1;

	long long out = 0;
	for (int i = 0; i < strlen(number); i++) {
		if (number[i] <= '9')
			out += ((long long)(number[i] - '0')) * pow(radix, times);
		if (number[i] >= 'a')
			out += ((long long)(number[i] - 'a' + 10))*pow(radix, times);
		times--;
	}
	return out;
}

// 查找字符串中ASCII码最大的字符,用于做二分查找下界
int FindMax(char* N) {
	int maxChar = '0';
	for (int i = 0; i < strlen(N); i++) {
		if (maxChar < N[i])
			maxChar = N[i];
	}

	if (maxChar <= '9')
		maxChar = maxChar - '0';
	if (maxChar >= 'a')
		maxChar = maxChar - 'a' + 10;
	return maxChar;

}

int main() {
	int maxChar = '0';
	char N1[11], N2[11];
	long long n1, n2, left, right, middle;
	int radix;
	int tag;

	cin >> N1 >> N2 >> tag >> radix;

	if (tag == 1) {
		// 将确定的数转换成10进制整数
		n1 = TransSystemToDec(N1, radix);
		// 获得不确定数字符串中ASCII码最大的字符,作为二分查找下界
		maxChar = FindMax(N2);
		// 初始化二分查找需要的变量
		left = maxChar + 1;
		right = n1 + 1; // 上界为确定数的十进制 +1,原因是比(确定数的十进制 + 1)再大的进制数,它对应的(确定数的十进制 +1)这个值在该进制下的表示都不会变化
		middle = (left + right) / 2;

		while (right >= left) {
			if (n1 == TransSystemToDec(N2, middle)) {
				cout << middle;
				return 0;
			}
			// 这里 || 运算符后面的判断用于过滤比 long long 数据类型还大的数据,这样的数据题目中是不会使其符合题意的
			if (n1 < TransSystemToDec(N2, middle) || (TransSystemToDec(N2, middle) < 0)) {
				right = middle - 1;
				middle = (left + right) / 2;
			}
			else {
				left = middle + 1;
				middle = (left + right) / 2;
			}

		}
		cout << "Impossible";
	}
	if (tag == 2) {
		n2 = TransSystemToDec(N2, radix);
		maxChar = FindMax(N1);
		left = maxChar + 1;
		right = n2 + 1;
		middle = (left + right) / 2;


		while (right >= left) {
			if (n2 == TransSystemToDec(N1, middle)) {
				cout << middle;
				return 0;

			}
			if (n2 < TransSystemToDec(N1, middle) || TransSystemToDec(N1, middle) < 0) {
				right = middle - 1;
				middle = (left + right) / 2;
			}
			else {
				left = middle + 1;
				middle = (left + right) / 2;
			}

		}
		cout << "Impossible";

	}
	return 0;
}

希望能帮到大家!

原文地址:https://www.cnblogs.com/Breathmint/p/10290244.html