1010 Radix (25 point(s)) 刷题踩坑记录

原题链接
下面给出我自己的ac代码

#include<cstdio>
#include<string>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
char Map[256];
void hashMap() {
	for (char c = '0'; c <= '9'; c++)
		Map[c] = c - '0';
	for (char c = 'a'; c <= 'z'; c++)
		Map[c] = c - 'a' + 10;
}
long long transformBinary10(string N1,long long radix) {
	long long ans = 0;
	for (int i = 0; i < N1.length(); i++) {
		ans = ans * radix + Map[N1[i]];
		if (ans < 0)
			return -1;
	}
	return ans;
}
long long setLeft(string N2) {
	long long ans = 1;
	for (int i = 0; i < N2.length(); i++) {
		if (ans < Map[N2[i]])
			ans = Map[N2[i]];
	}
	return ans;
}
long long setRight(long long N1,string N2) {
	if (setLeft(N2) > N1)
		return setLeft(N2) + 1;
	else
		return N1 + 1;
}
long long setBinary(string N2,long long N1) {
	long long l = setLeft(N2) + 1, r = setRight(N1, N2), m;
	while (l <= r) {
		m = (l + r) / 2;
		long long flag = transformBinary10(N2, m); 
		if (flag == -1) {
			r = m - 1;
			continue;
		}
		if (flag > N1)
			r = m - 1;
		else if (flag < N1)
			l = m + 1;
		else {
			return m;
		}
	}
	return -1;
}

int main() {
	string N1, N2, temp;
	long tag, radix;
	cin >> N1 >> N2 >> tag >> radix;
	hashMap();
	if (tag == 2) {
		temp = N1;
		N1 = N2;
		N2 = temp;
	}
	long long t = 0;
	t = transformBinary10(N1, radix);
	int ans = setBinary(N2, t);
	if (ans == -1)
		cout << "Impossible";
	else
		cout << ans;
	return 0;
}

踩坑点一:需要判断数据溢出情况。

一开始我是完全没有考虑到,数据会溢出,甚至采用的是int来存储数据。后来才发觉,转换进制的时候数据溢出是很常见的。不仅仅是要用long long数据类型存储,在转换过程中long long也可能数位不够而溢出。我们需要中途判断是否溢出。

踩坑点二:二分法上限(right)

看完题,我的固有思维告诉我计算得出的进制数应该是2到36。这导致了一堆的wrong answer。仔细想想,它的理论最大上界应该是N1。就算进制是无限大,我依然可以用给出的数字造出N2,并不会被这36个字符所限制。
但还有一个情况,就是N1是一个极小的数,如果直接取N1作为最大上界,会出现最大上界小于最小可能下届的情况,会直接输出Impossible。对于上界的选取需要做出一些判断:若N1的十进制大于N2的最小可能下届,我们取N1为最大可能上界;反之,我们取N2的最小可能下届+1为最大可能下届就像样例所指出那样,N1十进制小于N2的最大字符所代表的数字时,无论怎样都是找不到对应的进制的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值