1010 Radix (25 分)C++实现-终于AC了

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37407587/article/details/83537637

题目

题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536
是一道目前为止比较有意思的题,也是碰到的为数不多需要考虑上溢出的题目

知识点:整型上溢出, 二分查找

思路:

题目是一个进制转化问题,思路是将两个数都转化为10进制进行比较,对于未知数的base通过逐个base尝试转化为10进制数值和已知数比较.

坑点:

  1. int类型的最大值只有10^7数量级,故如果直接使用int很容易造成上溢出,考虑使用long long类型
  2. 逐个遍历在范围较大时会发生超时,故对于单调的搜索可以采用二分查找
  3. 搜索的上下界确定:搜索的下界易知是未知数的最大数字+1,但是上界在一开始没有想通,
    当未知数有两位以上时,例如10,此时base不能大于已知数val1,不然直接超过了,但是
    如果未知数只有1位,那么base只需要比数字大即可,在这种情形下,base_min == base_max = val2+1
  4. 如何判断溢出,当发生溢出时,会出现循环现象,int类型2147483647 加1后变为-2147483648,故判断是否
    溢出通常可以是否为负检查
  5. 8和10两个测试点没有过,答案错误
  6. 8测试点是溢出
    测试用例 9999999999 9999999999 1 16
    转为10base的时候, 不能直接用pow函数,类型转换会导致溢出,注意该函数里可能较大的变量都需要设为ll
  7. 10测试点是输入为0
    当其中一个输入为0时,base若等于最大数字加1则为1,但我们知道进制的最小值为2,故在搜索前需要进行检查

代码

#include <iostream>
#include<string>
#include <cmath>
#include <algorithm>
#define ll long long // int type will overflow with 7 digit based on 10
using namespace std;


// AC啦!!
void TestTrans(); // trans2ten() 边界测试函数
ll trans2ten(string s, int base); // 将以base为基的数s转为十进制数
int find_min_base(string s); // 查找最小的可能的基, 需要注意s为0的情况
int search_base(ll known, string s, ll low, ll high); // 二分查找基, 若找不到返回-1
int main()
{
	/*while (1) {
		TestTrans();
	}*/
	string s1, s2;
	int flag, base;
	ll base_min, base_max;
	ll known;
	cin >> s1 >> s2 >> flag >> base;
	if (flag == 2) swap(s1, s2); // easier for the following application.
	known = trans2ten(s1, base);
	base_min = find_min_base(s2);
	base_max = max(known, (long long)base_min);
	int result = search_base(known, s2, base_min, base_max);
	if (result == -1) cout << "Impossible" << endl;
	else cout << result << endl;
	getchar();
	getchar();
	return 0;
}
ll trans2ten(string s, int base)
{
	ll sum = 0;
	ll exp = 1;
	ll digit;
	for (int i = s.size() - 1; i >= 0 && sum >= 0; i--) {
		if (s[i] >= '0' && s[i] <= '9')
			digit = s[i] - '0';
		else if (s[i] >= 'a' && s[i] <= 'z')
			digit = s[i] - 'a' + 10;
		else digit = 0;
		sum += digit * exp;
		exp *= base;
	}
	return sum;
}
void TestTrans() {
	string s;
	int base;
	cin >> s >> base;
	cout << trans2ten(s, base);
}

int find_min_base(string s)
{
	int base = 0;
	int digit;
	for (int i = s.size() - 1; i >= 0; i--) {
		if (s[i] >= '0' && s[i] <= '9')
			digit = s[i] - '0';
		else if (s[i] >= 'a' && s[i] <= 'z')
			digit = s[i] - 'a' + 10;
		else digit = 0;
		if (digit > base) base = digit;
	}
	return digit + 1; // base is always larger than digit.
}

int search_base(ll known, string s, ll low, ll high)
{
	if (low < 2) low = 2; // check the base if N2 is 0.
	ll left = low, right = high, middle = (low + high) / 2;
	while (left <= right)
	{
		ll sequence = trans2ten(s, middle);
		if (sequence < 0 || sequence > known) {
			right = middle - 1;
		}
		else if (sequence < known) {
			left = middle + 1;
		}
		else return middle;
		middle = (left + right) / 2;
	}
	return -1;
}

猜你喜欢

转载自blog.csdn.net/m0_37407587/article/details/83537637