PAT A 1010

思路:

  1. 将确定进制的数放在N1,未确定进制的数放在N2。(利用strcpy()函数)
  2. 将N1转换为十进制,然后二分N2的进制,将N2从假设的进制转换为十进制。如果大于N1的十进制,则假设的进制过大,应该往左子区间继续二分;如果小于,则假设的进制过小,继续往右子区间二分。

tips:大概需要三个子函数:1)把数转换为十进制;2)将N2的十进制与t进行比较;3)二分法
还有需要求出N2中的最大数位,+1作为二分法的下界。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL Map[256];
LL inf=(1LL << 63)-1;
void init(){
	for(char c='0';c<='9';c++){
		Map[c]=c-'0';  //将0-9映射到0-9 
	}
	for(char c='a';c<='z';c++){
		Map[c]=c-'a'+10; //将'a'-'z'映射到10-35 
	}
}
LL convert10(char a[],LL radix,LL t){  //转换十进制数,t为上界
	LL ans=0;
	int len=strlen(a);
	for(int i=0;i<len;i++){
		ans=ans*radix+Map[a[i]];   //进制转换
		if(ans <0|| ans>t) return -1;   //溢出或者超过N1的进制 
	}
	return ans;
}
int cmp(char N2[],LL radix,LL t){ //N2与t进行比较
	int len=strlen(N2);
	LL num=convert10(N2,radix,t);  //将N2转换为十进制 
	if(num<0) return 1;  //溢出或者超过N1的进制,N2肯定比N1大 
	if(t > num) return -1;   //t较大,返回-1 
	else if(t==num) return 0; //相等,返回0 
	else return 1; //num较大,返回1 
}
LL find_radix(char N2[],LL left,LL right,LL t){  //二分求解N2的进制
	LL mid;
	while(left<=right){
		mid=(left+right)/2;
		int flag=cmp(N2,mid,t); //以中间值为进制数,比较N2[]与t的大小 
		if(flag==0) return mid;  //找到解,返回结果 
		else if(flag==-1) left=mid+1;  //t较大,进制数太小了,往右子区间找 
		else right=mid-1;  //t较小,进制数太大了,往左子区间找 
	}
	return -1;//没找到 
}
int findDigit(char N2[]){
	int ans=-1,len=strlen(N2);
	for(int i=0;i<len;i++){   //找出N2[]中最大的位置数 
		if(Map[N2[i]]>ans)
			ans=Map[N2[i]];
	}
	return ans+1;   //最高的数位为ans,进制则为ans+1 
} 
char N1[20],N2[20],temp[20];
int tag,radix;
int main(){
	init();
	scanf("%s %s %d %d\n",N1,N2,&tag,&radix);
	if(tag==2){//交换N1和N2
		strcpy(temp,N1);
        strcpy(N1,N2);
        strcpy(N2,temp);
	}
	LL t=convert10(N1,radix,inf);//将N1转换为十进制数 
	LL low=findDigit(N2); //找到N2中数位最大的位+1,作为二分下界
	LL high=max(low,t)+1;  //上界
	LL ans=find_radix(N2,low,high,t); //二分 
	if(ans==-1) printf("Impossible\n");
	else printf("%lld\n",ans);
	return 0;   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值