题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536
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
:题意 给出两个数字n1,n2,tag和进制r,如果tag=1,说明n1是r进制数,求n2在几进制的情况下与n1相等。如果tag=2,说明n2是r进制数,求n1在几进制的情况下与n2相等。
:思路 题解一般用的是二分查找法,水水说如果这样做他很难确定上界是多少,然后就用的特判来避免的超时。
首先,这两个数字都是以字符形式输入的,len1表示未知进制数的长度,len2表示已给出进制数的长度。将各个位上的字符转化为数字。
- 比较未知进制数的各个位上数字并求出最大值st,也就是查询几进制能满足相等条件 这个进制的下界。
- 将已知r进制数转为10进制数ans,用于比较。
- 将进制从st开始跑,将 i 进制数转十进制的结果ans1 并与ans进行比较,如果相等就输出 i 进制,如果大于输出 Impossible。
但是这样做会超时,可以想一下如果已知进制的数字转为十进制是10000000000,未知是100,那么循环跑的最大进制是100000,时间复杂度是根号n,如果未知是10,那么循环的最大进制是10000000000,时间复杂度是n。
避免超时的方式是特判:未知进制数是1位和两位的情况
- 如果未知进制数是一位,无论几进制均是其本身,只需比较ans与一位未知进制数。
- 如果未知进制数是两位,由于最末位数字不影响比较,那么需判断首位数字c[0]与ans(ans=ans-未知进制数最末位上的数)能否组成倍数关系,其倍数也就是进制数。例:已知数字的十进制为11,未知进制数是32(减掉最末位11→9、9/3=3 但是三进制中最大数字为2,所有不可能相等);再例如:十进制为11,未知进制是23(减掉最末位11→8、8/2=4并且2和3均小于4,故23在4进制的条件下等于11)
#include<iostream>
#include<cstring>
using namespace std;
int main(){
char a[11],b[11];
long long tag,r;
long long c[11];
cin>>a>>b>>tag>>r;
long long st=-1;
int len1,len2;//让len1存未知进制数的长度
long long ans=0;
if(tag==1){
len1=strlen(b);
len2=strlen(a);
for(int i=0;i<len1;i++){
if(b[i]>='0'&&b[i]<='9'){
c[i]=b[i]-'0';
}else{
c[i]=b[i]-'a'+10;
}
st=max(st,c[i]);
}
long long t;
long long k=1;
for(int i=len2-1;i>=0;i--){
if(a[i]>='0'&&a[i]<='9'){
t=a[i]-'0';
}else{
t=a[i]-'a'+10;
}
ans+=t*k;
k*=r;//r进制转10进制
}
}else{
len1=strlen(a);
len2=strlen(b);
for(int i=0;i<len1;i++){
if(a[i]>='0'&&a[i]<='9'){
c[i]=a[i]-'0';
}else{
c[i]=a[i]-'a'+10;
}
st=max(st,c[i]);
}
long long t;
long long k=1;
for(int i=len2-1;i>=0;i--){
if(b[i]>='0'&&b[i]<='9'){
t=b[i]-'0';
}else{
t=b[i]-'a'+10;
}
ans+=t*k;
k*=r;//r进制转10进制
}
}
//特判未知进位数为一位和两位,否则会超时。
if(len1==1){
if(c[0]!=ans){
cout<<"Impossible"<<endl;
} else{
cout<<st+1<<endl;
}
return 0;
}
if(len1==2){
ans=ans-c[1];
if(ans%c[0]!=0){
cout<<"Impossible"<<endl;
}else{
long long mm=ans/c[0];
if(mm>c[0]&&mm>c[1]){
cout<<mm<<endl;
}else{
cout<<"Impossible"<<endl;
}
}
return 0;
}
//进制从未知数的最大一位上的数字+1开始跑
for(long long i=st+1;;i++){
long long ans1=0;
long long k1=1;
for(int j=len1-1;j>=0;j--){
ans1+=c[j]*k1;
k1*=i;
}
if(ans1==ans){
cout<<i<<endl;
break;
} else if(ans1>ans){
cout<<"Impossible"<<endl;
break;
}
}
return 0;
}