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出现负数减少进制即可;