PAT A1010 Radix 膜!算法笔记题解

在这里插入图片描述
这道题是有点坑的,题意表述上没有明确,radix的值并不在(0,36)之间,所以暴力遍历是行不通的
反正也不会o(╥﹏╥)o
看了下算法笔记关于这道题的题解,根据题解中所述,假定已知的radix都是N1的(若不是则交换),则转换为10进制后N1不会超过long long 的范围,故仅需对N2转换的时候进行判断其是否溢出。
下面是算法笔记的源代码:

using namespace std;
#include<bits/stdc++.h>
long long Map[256],inf=(1LL<<63)-1;
char n1[20],n2[20],tmp[20];
int tag,radix;

void init(){
//point1
	for(char c='0';c<='9';c++) Map[c]=c-'0';
	for(char c='a';c<='z';c++) Map[c]=c-'a'+10;
}

long long convertNum10(char a[],int radix,long long t){
	long long 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; //point2
	}
	return ans;
}

long long findLargestDigit(char a[]){
	int ans=0;
	int len=strlen(a);
	for(int i=0;i<len;i++)
	{
		if(Map[a[i]]>ans) ans=Map[a[i]];
	}
	return ans+1; //point3
}

int cmp(char a[],long long radix,long long t){
	int len=strlen(a);
	long long num=convertNum10(a,radix,t);
	if(num<0) return 1;
	if(t>num) return -1;
	else if(t == num) return 0;
	else return 1; //point4
}

long long binarySearch(char a[],long long left,long long right,long long t){
	long long mid;
	while(left<=right)
	{
		mid=(left+right)/2;
		int flag=cmp(a,mid,t);
		if(flag == 0) return mid;
		else if(flag == -1) left=mid+1;
		else right=mid-1;
	}
	return -1;
}

int main(){
	init();
	cin>>n1>>n2>>tag>>radix;
	if(tag == 2)
	{
		strcpy(tmp,n1);
		strcpy(n1,n2);
		strcpy(n2,tmp);
	}
	long long t,low,high,ans;
	t=convertNum10(n1,radix,inf);
	low=findLargestDigit(n2);
	high=max(t,low)+1; //point5
	ans=binarySearch(n2,low,high,t);
	if(ans == -1) cout<<"Impossible\n";
	else cout<<ans;
	return 0;
}

point1:init()函数中for循环,直接对char进行循环,写的真的很好(反正我是想不到这样写╮(╯▽╰)╭),而且这也是我第一次见到这么写for循环的(暴露了自己做题很少的事实了);

point2 && point4:if(ans<0 || ans>t) return -1; 中ans>t这句实际上是不需要的,因为一方面 t = inf 时ans就是long long类型,ans<0 就是ans>inf 了,另一方面t != inf 而是N1的十进制值时,因为后面point4处有判断所以这里其实不需要,加上的话,point4处的那条语句就永远不会执行了,num>t的情况已经变成了num<0了;

point3:这里一定要注意,我们遍历N2字符数组找到最大的数后,一定要+1才是当前进制的下界呀;

point5:这里我开始没能理解,为什么N2的radix的上界是【N2的下界和N1的10进制值】取最大后+1,后来又在csdn上看到一篇有关这题的blog,发现他也写到了此处,若N1的10进制值>N2的下界,则N2的进制是不会比N1的10进制值+1还大的,不然N2即使为“10”也不符合。

虽然这道题归类是二分,但其实这道题二分的函数是很好写的,就是个模板,难得就是怎么想到这种思路,确定上下界以及字符和数字间的处理。

下面是我根据point2 && point4 稍微修改后的代码:

using namespace std;
#include<bits/stdc++.h>
long long Map[256];
char n1[20],n2[20],tmp[20];
int tag,radix;

void init(){
	for(char c='0';c<='9';c++) Map[c]=c-'0';
	for(char c='a';c<='z';c++) Map[c]=c-'a'+10;
}

long long convertNum10(char a[],int radix){
	long long ans=0;
	int len=strlen(a);
	for(int i=0;i<len;i++)
	{
		ans=ans*radix+Map[a[i]];
		if(ans<0) return -1;
	}
	return ans;
}

long long findLargestDigit(char a[]){
	int ans=0;
	int len=strlen(a);
	for(int i=0;i<len;i++)
	{
		if(Map[a[i]]>ans) ans=Map[a[i]];
	}
	return ans+1;
}

int cmp(char a[],long long radix,long long t){
	int len=strlen(a);
	long long num=convertNum10(a,radix);
	if(num<0) return 1;
	if(t>num) return -1;
	else if(t == num) return 0;
	else return 1;
}

long long binarySearch(char a[],long long left,long long right,long long t){
	long long mid;
	while(left<=right)
	{
		mid=(left+right)/2;
		int flag=cmp(a,mid,t);
		if(flag == 0) return mid;
		else if(flag == -1) left=mid+1;
		else right=mid-1;
	}
	return -1;
}

int main(){
	init();
	cin>>n1>>n2>>tag>>radix;
	if(tag == 2)
	{
		strcpy(tmp,n1);
		strcpy(n1,n2);
		strcpy(n2,tmp);
	}
	long long t,low,high,ans;
	t=convertNum10(n1,radix);
	low=findLargestDigit(n2);
	high=max(t,low)+1;
	ans=binarySearch(n2,low,high,t);
	if(ans == -1) cout<<"Impossible\n";
	else cout<<ans;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值