1010 Radix (25 point(s))
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
进制转换、二分查找。这道题非常坑,题目的表达也很容易让人误解。
对于进制转换,有基于大数除法的模板(18分)。
然而实际上,题目并没有限制进制最大是36(但我认为它也没有说得很明白)。比如10进制下的10000(D)可以表示成9999进制下的11(1*9999+1==10000),10进制下的10000也可以表示成10000进制下的10。
思路:首先把已知进制数的数转换成10进制A,然后对于未知进制的数B按照i进制转换,如果转换的数和A相等则可。如何确定可以转换进制的范围呢?使用二分查找。下界是B中出现最大的数字(digit)加1,上界是10进制的A的值。
注意点:1.int不够;2. 溢出情况;3. 二分查找的上下线;4. tag的处理;5. 题意!
大神对于各种坑的总结:https://blog.youkuaiyun.com/Joyceyang_999/article/details/81908299
#include<iostream>
#include<cstring>
using namespace std;
string conv(int n,string num,int m){//n to m
string ans="";
int len = num.length();
for(int i=0;i<len;){
int remain = 0;
for(int j=i;j<len;j++){
if(num[j]>='0'&&num[j]<='9') remain = n*remain+num[j]-'0';
else remain=n*remain+num[j]-'a'+10;
int temp = remain/m;
if(temp>=0&&temp<=9) num[j]=temp+'0';
else num[j]=temp-10+'a';
remain=remain%m;
}
if(remain>=0&&remain<=9) ans=char(remain+'0')+ans;
else ans = char(remain+'a'-10)+ans;
while(num[i]=='0')i++;
}
return ans;
}
int main(void){
string N1,N2;int tag,radix;
cin>>N1>>N2>>tag>>radix;
bool flag = false;
if(tag==1){
for(int i=2;i<=36;i++){
if(conv(radix,N1,i)==N2){
flag=true;
cout<<i<<endl;
break;
}
}
}
else if(tag==2){
for(int i=2;i<=36;i++){
if(conv(radix,N2,i)==N1){
flag=true;
cout<<i<<endl;
break;
}
}
}
if(!flag) cout<<"Impossible"<<endl;
return 0;
}
AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
ll char2digit(char c){
if(c>='0'&&c<='9') return c-'0';
else return c-'a'+10;
}
ll toDec(string s,ll radix){
ll ans = 0;
for(int i=0;i<s.length();i++){
ans=radix*ans+char2digit(s[i]);
if(ans<0) return -1;
}
return ans;
}
int main(void){
string n1,n2;int tag,radix;
cin>>n1>>n2>>tag>>radix;
if(tag==2) swap(n1,n2);
ll mid,left,right,target;
target = toDec(n1,radix);//把目标数转换成十进制
left = 2;
for(int i=0;i<n2.size();i++) left = max(left,1+char2digit(n2[i]));
right = max(left,target);
while(left<=right){
mid = (left+right)>>1;
ll temp = toDec(n2,mid);
if(temp>=target||temp==-1)//根据当前进制转换的数过大
right = mid-1;
else//反之
left = mid+1;
}
if(toDec(n2,left)==target) cout<<left<<endl;//验证
else cout<<"Impossible"<<endl;
return 0;
}