pat 甲1010. Radix(二分)

9 篇文章 0 订阅

1010. Radix (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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
详细的说下这个题目的题解:
题目的描述是:给定一个确定进制的数,问是否存在某一个进制使得的数字等于给定的数字;题目没有给定最大进制数,采用long long合适。
 
 
处理方式:全部转换为十进制数字。看对应是否相等。单调进制显然可以采用二分的方式。否则会超时。
要处理的细节:
1.符合要求的进制可能不止一个。如何输出最小进制。(这个对应了测试点一)
我一开始误以为,当两个字符串完全相等时会发生这种情况。
实际上是待求进制的数字只有一位时可能有多个进制满足要求(例如 11 b 1 10)。我们的处理方式时,最小进制数是给定的数字+1;
 
 
2.测试点7,先经历了超时 后来答案错误。处理的关键是最小的进制是出现的位数最大的数字加1(包括字母),比如8az,这个数字的最小进制应该是36。
最大的进制数子一开始取1e9,发现答案错误。到最后测试了百亿级别,答案正确。
实际上最大的进制数 是已经给定数字再加1. 大家想一想为什么?

3.在二分查找的过程中,可能会出现溢出的情况,我的处理方式时,每次累加过程中进行比较,一旦溢出,或者大于给定的数字则进行下一次二分。
 
 
先贴出正确的代码...然后错误的代码以示警示:
#include<iostream>
#include<cctype>
#include<string>
using namespace std;

string s1,s2,s3,s;//s3给定的数(字符串形式),s待确定进制的数 
long long radix,tag,a,b;//a给定进制的数,b待求进制的数 

int judge(long long r)//用于比较a和b的大小,以及判断b是否会溢出
{
	b=0;
	for(int i=0;i<s.size();i++)
	{
		if(isdigit(s[i]))
		{
			b=b*r+(s[i]-'0');
		}
		else 
		b=b*r+(s[i]-'a'+10);
		if(b>a||b<0)
		{
			return 1;//表示发生了溢出,或者进制太大; 
		 } 
	}
	
	if(b==a)return 0;//表示找到了当前进制;
	else if(b<a)return -1;//表示当前的进制较小; 
	
 } 
 
int main()
{
	cin>>s1>>s2>>tag>>radix;
	if(tag==1){
		s3=s1;s=s2;
	}else {
		s3=s2;
		s=s1; 
	}
	
	
	long long left,right;
	
	
	char _max='0';
	//寻找最小进制left 
	for(int i=0;i<s.size();i++)
	{
		_max=max(_max,s[i]);
	}
	if(isdigit(_max))left=_max-'0'+1;
	else left=_max-'a'+11;
	
	
	//求出给定的数字 
	for(int i=0;i<s3.size();i++)
	{
		if(isdigit(s3[i]))
			a=a*radix+(s3[i]-'0');
		else 
			a=a*radix+(s3[i]-'a'+10);
	}
	
	//此处是对进制不唯一情况的处理 ,当待求数字只有一位时。 
	if(s.size()==1)
	{
		if(isdigit(s[0]))
		{
			if((s[0]-'0'==a))
			cout<<left<<endl;
		}
		else
		{
			if(s[0]-'a'+10==a)
			cout<<left<<endl;
		}
		return 0;
	}
	

	//最大进制: 
	right=a+1;
	
//	right=100 0000 0000; 这个也能过 
	while(left<=right)
	{
		long long mid =(left+right)/2;
			
		int flag=judge(mid);
		
		if(flag==1)right=mid-1; 
		else if(flag==0)
		{
			cout<<mid<<endl;
			return 0;
		}
		else left=mid+1;
	}
	
	cout<<"Impossible"<<endl;	
	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值