PAT A1010 Radix

原文链接: PAT A1010 Radix

上一篇: 完美数列 PAT A1085

下一篇: PAT A1044. Shopping in Mars (25)

https://www.patest.cn/contests/pat-a-practise/1010

Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is "yes", if 6 is a decimal number and 110 is a binary number.

Now for any pair of positive integers N1 and N2, your task is to find the radix of one number while that of the other is given.

Input Specification:

Each input file contains one test case. Each case occupies a line which contains 4 positive integers:
N1 N2 tag radix
Here N1 and N2 each has no more than 10 digits. A digit is less than its radix and is chosen from the set {0-9, a-z} where 0-9 represent the decimal numbers 0-9, and a-z represent the decimal numbers 10-35. The last number "radix" is the radix of N1 if "tag" is 1, or of N2 if "tag" is 2.

Output Specification:

For each test case, print in one line the radix of the other number so that the equation N1 = N2 is true. If the equation is impossible, print "Impossible". If the solution is not unique, output the smallest possible radix.

Sample Input 1:

6 110 1 10

Sample Output 1:

2

Sample Input 2:

1 ab 1 2

Sample Output 2:

Impossible

注意:

  • 1.input 中两个数字可以是 10 位数,虽然没有告诉 radix 的范围,但在 9*10^10 10 1 200 这个示例中,可以看到结果的 radix 也可以是很大的。从这个角度看,代码中将 radix 和两个数值都设定为 longlong 是合适的选择。
  • 2.在计算另一个数的 radix 时,简单的遍历 [2, 1018]会超时。单调的区间很自然想到使用二分查找。
  • 3.二分查找的上下界确定能减少耗时:下界选数字的所有位上的最大值+1;上界容易想当然的认为就是题中给定了 radix 的数的值。实际上,示例 11 b 1 10 就是一个反例,原因在于这个假设忽略了一位数的可能性,解决方案是在取给定 radix 的数值和下界中较大的那个数。
  • 4.在二分查找时,不可直接计算出某个 radix 下数的值,因为可能会 longlong 溢出。于是需要用特定的 compare 函数,在累加的过程中判定是否大于另一个数。算是一种剪枝。
  • 5.还有一个条件:当两个数都是 1 时,输出 2.当两个数相等且不为 1 时,输出题中给出的 radix。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
LL map[256];	//字符与数值的对应 0-9 - 0-9 a-z 与 10-35 
const LL INF = (1LL << 63) - 1;
void init() {
	for (char c = '0'; c <= '9'; c++)
		map[c] = c - '0';
	for (char c = 'a'; c <= 'z'; c++)
		map[c] = c - 'a' + 10;
}

//将a转换为十进制,t是上界 
LL convertNum10(char a[], LL radix, LL t) {
	LL ans = 0;
	int len = strlen(a);
	for (int i = 0; i < len; i++) {
		ans = ans * radix + map[a[i]];
		if (ans<0 || ans>t) return -1;	//溢出或者超过N1的十进制 
	}
	return ans;
}

//N2的十进制与t比较 
int cmp(char N2[], LL radix, LL t) {
	int len = strlen(N2);
	LL num = convertNum10(N2, radix, t); //将N2转换为十进制
	if (num < 0) return 1;	//溢出,肯定N2>t 
	if (t > num) return -1;	//t较大,返回-1 
	else if (t == num) return 0;	//相等返回0 
	else return 1;		//num较大,返回1 

}

//二分求解N2的进制 
LL binarySearch(char N2[], LL left, LL right, LL t) {
	LL mid;
	while (left <= right) {
		mid = (left + right) / 2;
		int flag = cmp(N2, mid, t);
		if (flag == 0) return mid;
		else if (flag == -1) left = mid + 1;
		else right = mid - 1;
	}
	return -1;
}

//求最大数位 
int findAns(char N2[]) {
	int ans = -1, len = strlen(N2);
	for (int i = 0; i < len; i++)
		if (map[N2[i]] > ans)
			ans = map[N2[i]];
	return ans + 1;	//最大的数位是ans,说明进制数的底线是ans+1 
}

char N1[20], N2[20], tmp[20];
int tag, radix;
int main(int argc, char *argv[]) {
	init();
	scanf("%s %s %d %d", N1, N2, &tag, &radix);
	if (tag == 2) {  //交换N1,N2
		strcpy(tmp, N1);
		strcpy(N1, N2);
		strcpy(N2, tmp);
	}
	LL t = convertNum10(N1, radix, INF);
	LL low = findAns(N2);
	LL high = max(low, t) + 1;
	LL ans = binarySearch(N2, low, high, t);
	if (ans == -1)
		printf("Impossible\n");
	else
		printf("%lld\n", ans);

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值