PAT 算法笔记 Radix

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、题目中说以0-9和a-z表示0-35,很容易就误认为最大进制为36,但事实上最大进制可能远远大于36。最开始我在实现时就简单地使用了for循环从2开始遍历到10,但事实上这即忽略了上界又忽略了下界。如何确定上下界呢?

下界:最大数位的值加1,如1001的下界为2,6007的下界为8;

上界:将已知进制的数(N1或N2)转化为十进制的值N,与下界中较大的那一个再加1。

2、在将N1或N2转换为十进制时可能会发生溢出,如何判断呢?

转换后小于0即溢出,此时说明当前进制太大,right应变为mid-1。

3、使用long long类型,注意不要一些变量用int,一些用long long,尽量统一使用long long,这样就不用花时间在long long类型和int类型之间的转换上。

4、使用for循环挨个判断,测试点7会超时,需要使用二分法

参考解法:

#include <stdio.h>
#include <string.h>

char num[2][11];
long long n;

long long changeIntoNum(long long tag, long long radix)
{
	long long res = 0;
	for(int i = 0; i < strlen(num[tag]); i++)
	{
		long long temp;
		if(num[tag][i] >= '0' && num[tag][i] <= '9')
		{
			temp = num[tag][i] - '0';
		}
		else
		{
			temp = num[tag][i] - 'a' + 10;
		}		
		res = res * radix + temp;
	}
	return res;
}

int cmp(long long tag, long long left, long long right)
{
	long long mid;
	long long cur;
	//二分法找最小的进制 
	while(left <= right)
	{
		mid = (right + left) / 2;
		cur = changeIntoNum(tag, mid);		
		if(cur == n) return mid;
		else if(cur < 0 || cur > n) right = mid - 1;
		else left = mid + 1;
	}
	
	//使用for循环会超时 
//	for(int i = left; i <= right; i++)
//	{
//		if(changeIntoNum(tag, i) == n) return i;
//	}
	return -1;
}

long long findLargestDigit(long long tag)
{
	long long max = 0;
	
	for(int i = 0; i < strlen(num[tag]); i++)
	{
		long long temp;
		if(num[tag][i] >= '0' && num[tag][i] <= '9')
		{
			temp = num[tag][i] - '0';
		}
		else
		{
			temp = num[tag][i] - 'a' + 10;
		}
		if(temp > max) max = temp;
	}
	
	return max + 1;
}

int main()
{
	long long tag, radix;
	scanf("%s %s %lld %lld", num[0], num[1], &tag, &radix);
	
	tag--;
	
	n = changeIntoNum(tag, radix);
	
	if(tag == 0) tag = 1;
	else tag = 0;
	
	long long low = findLargestDigit(tag);
	long long high = (low > n ? low: n) + 1;
	
	long long r = cmp(tag, low, high);
	
	if(r != -1) printf("%lld", r);
	else printf("Impossible");
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值