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: 和其他人一样一开始,我觉得进制只能是1-35, 因此用了strtol函数,后来发现虽然给了35个字符,但是表示的时候可以不使用其他字符!
c++strtol只支持2-35进制的,因此不能用该函数。
2: 另一个问题是范围:这题long long是不够的,需要unsigned long long
3: 这题的本质是求F(radix)=N的最小解,网上很多人用二分法,不得不说二分法确实是最适合的。上界取N+1即可,下界取1,然后迭代。二分法退出条件是i<=j,这个注意
如果出现radix小于某一位数字的时候,必须返回一个很小的数,比如0,这样在调整的时候可以把radix调大一点。
对于网上某些人出现的8 8 1 10返回除了9之外的情况,好像是上界选取的问题。
4: 为什么上界选N+1,是否可能存在更小的上界?
对于方程F(x)=N, 当F(x)=N*x^0时,方程的解有无数个,是N+1, N+2,…(x必须大于N)
当x的最高非0项指数更大时,方程F(x)-N在x>0是单调的,因此最多可能有一个解。这个解一定小于N+1,因为F(N+1)-N>=0, 即F(N+1)处已经大于0,在单增的函数下,不可能有比N+1更大的解了。
因此,为了让方程始终有一个解,我们设定解的范围最大是N+1,这样在第一种情况下,取得的是最小解,在剩下情况下,不会影响解的计算。
#include<iostream>
#include<math.h>
using namespace std;
unsigned long long int strtoll(string N,unsigned long long int radix){
long long int res=0;
long long int base=1;
for(int i=N.length()-1;i>=0;i--){
long long int num;
if(N[i]<='z'&&N[i]>='a') num=N[i]-'a'+10;
else num=N[i]-'0';
if(num>=radix) return 0;
res+=base*num;
base*=radix;
}
return res;
}
int main(){
string N1,N2;
int radix,tag;
cin>>N1>>N2>>tag>>radix;
if(tag==2){
string t=N1;N1=N2;N2=t;
}
unsigned long long int N=strtoll(N1,radix);
unsigned long long int left=1;
unsigned long long int right=(N<=10)?N+1:N;
unsigned long long int ans;
while(left<=right){
ans=(left+right)/2;
unsigned long long int t=strtoll(N2,ans);
if(t==N){
cout<<ans;
return 0;
}
if(t<N) left=ans+1;
if(t>N) right=ans-1;
}
cout<<"Impossible";
}