进制转换+二分查找 1010 Radix (25分)

1010 Radix (25分)

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 N
​1
​​ and N
​2
​​ , 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

解题
给出一个数的进制,求另一个数为什么进制可以与该数相等;

将第一个数转化为十进制,另一个数按每一种可能的进制方式转化为10进制,两者比较是否相等;

大数越界:
数有可能超过longlong可表示的范围,转为负值,说明进制过大,往小了算;

题目中没有给出进制大小,故最高进制可能为第一个数的十进制值。

注意点
给定的数实在36进制以内表示,但是转化的数可以转换成任意进制
所以需要得到待转化数进制的下边和上边;

下边
待转化数种每一个字符的最大值:

char it = *max_element(n.begin(), n.end());
low = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;

该函数需要 include < algorithm >

上边
给定数的十进制值和下边 两者的大值;

high = max(num, low);

故需要遍历low和high之间的每一个进制,看是否可以与给定数据相等;

1.输入函数

#include<iostream>
#include<string> 
#include<cmath>
#include<algorithm>
using namespace std;

string N1,N2;
int tag,radix;

void input()
{
	cin>>N1>>N2>>tag>>radix;		
}

2.将进制为n的Num转化为10进制的longlong

从前往后的进制转换

long long Radix(string Num, int n)
{
	//n为原本进制,结果转为10进制
	long long res=0;
	
	for(int i=0;i<Num.length();i++)
	{
		if(Num[i]>='0'&&Num[i]<='9') res = res*n+Num[i]-'0';  //从前往后进制转换 
		else  res= res*n+Num[i]-'a'+10;
	 } 
	return res;	 
}

3.判断两个不同进制的数是否相同

isdigit() 判断该字符是否为0-9之间的数;

void judge(string n1,string n2)
{
	long long tmp1= Radix(n1,radix);
	long long tmp2;
	bool flag=false;
	long long R;
    char it = *max_element(n2.begin(), n2.end());    //最大的数
    long long low = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;  //最低进制
    long long high = max(tmp1, low);                 // 最高进制
	for(long long i=low;i<=high;i++)
	{
		tmp2=Radix(n2,i);
		if(tmp2==tmp1) {
			flag=true;
			R=i;
			break;
		}
	}
	
	if(flag) cout<<R;
	else cout<<"Impossible";
	
}

4.main函数

int main()
{
	input();
	if(tag==1)
	judge(N1,N2);
	else 
	judge(N2,N1);
}

加入二分查找(顺序查找大数超时)

#include<iostream>
#include<string> 
#include<cmath>
#include<algorithm>
using namespace std;

string N1,N2;
long long tag,radix;

void input()
{
	cin>>N1>>N2>>tag>>radix;		
}

long long Radix(string Num, long long n)
{
	//n为原本进制,结果转为10进制
	long long res=0;
	
	for(int i=0;i<Num.length();i++)
		if(Num[i]>='0'&&Num[i]<='9') res = res*n+Num[i]-'0';  //从前往后进制转换 
		else  res= res*n+Num[i]-'a'+10;
		
	return res;	 
}

void judge(string n1,string n2)
{
	long long tmp1= Radix(n1,radix);
	long long tmp2;
	bool flag=false;
    char it = *max_element(n2.begin(), n2.end());    //最大的数
    long long low = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;  //最低进制
    long long high = max(tmp1, low);                 // 最高进制
    long long mid;
    
    while(low<=high){
    	mid = low+(high-low)/2;
    	tmp2=Radix(n2,mid);
    	if(tmp2 == tmp1) 
		{
			flag=1;
			break;
		} 
		else if(tmp2>tmp1||tmp2<0) high=mid-1;
		else low=mid+1;
	}
	if(flag) cout<<mid;
	else cout<<"Impossible";
	
}

int main()
{
	input();
	if(tag==1)
		judge(N1,N2);
	else 
		judge(N2,N1);
}

注意点

    while(low<=high){
	mid = low+(high-low)/2;
	tmp2=Radix(n2,mid);
	if(tmp2 == tmp1) 
	{
		flag=1;
		break;
	} 
	else if(tmp2>tmp1||tmp2<0) high=mid-1;
	else low=mid+1;
}

二分查找当longlong溢出时为负数,需要减小进制——high=mid-1;
该条件要写在tmp2<tmp1前面,因为负数一定小于tmp1;

总结
longlong的范围 正数——2^63;
测试数据给的最多10位数字,转为10位数longlong不会爆;
而把tmp2转为过大的进制会超longlong,所以tmp2出现负数减少进制即可;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值