1010 Radix (25 point(s))

本文解析了1010 Radix问题,探讨了如何通过二分查找和进制转换找到使两个正整数相等的基数。文章提供了详细的AC代码示例,包括将一个基数的数转换为另一个基数的函数实现,以及如何通过二分查找高效地找到可能的基数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 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

进制转换、二分查找。这道题非常坑,题目的表达也很容易让人误解。

 对于进制转换,有基于大数除法的模板(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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值