PAT 1010 Radix (25)

先看题目:



这个题目算是比较DT,花了很长时间,提交次数很多,每次都会有测试点没通过,后来网上搜索了一下,有一些特俗边界条件被我们忽略。

1,首先求目标数据进制,这个进制在任何条件下面都不能小于2,最大多少呢,不能局限于36,请想象多大都是有可能的,有多大,这么大!所以必须用long long int数据类型,这个一开始一直是被遗忘的角落。

2,由于数据搜索范围太大,穷举法一个for循环显然太慢了,肯定要超时的,最终就选则二分法查找。那么问题来了,二分法查找搜索上下边界是多少呢。这个好办,目标待求字符串的最小进制一定要比它所包含字符最大值还要大1,例如N2="456ad",最大字符是'd',所以最小应该是13+1=14,,这就对了吗?当然不对万一,我输入的N2="0"呢

最大字符'0',然后0+1=1,这是不对的,最小值是2才对。那么它的上限是多少呢,上限当然不能超过另外一个数据的十进制大小,因为N2不为0情况下,最小个位数都是1,如果它的进制再超过N1的十进制数了的话,它在十进制下的数也就比N1还要大,不符合要求。

3,如果一开始,输入两个数据N2最小进制都比N1的十进制数据还要大的话,怎么办呢。N2最小进制的最大数据也就36,出现这种情况也就说明N1在十进制下肯定比36小,二分查找上限就不能是N1在十进制时候的数了,应该改为36。

几个特俗测试点容易被遗忘 0 0 1 100以及12 c 1 10

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
long long jinzhi(char str[],long long radix);
int maxstr(char str[]);
long long BinSear(long long target,char str[],long long low,long long high);
int compare(char str[],long long radix,long long target);

int main()
{
	char N1[11]={0};
	char N2[11]={0};
	int tag;
	long long radix;//此处输入有可能超过int表示范围 
	cin>>N1>>N2>>tag>>radix;
	
	long long low,high,heji=0;
	if(tag==1)
	{
		heji=jinzhi(N1,radix);
		long long temp=(long long)maxstr(N2)+1;//此处temp最小值为2,最大值为36 
		if(heji<=temp)//如果了heji比temp还要小 
		{
			long long linshi=BinSear(heji,N2,temp,36);//待求进制数介于temp到36之间 
			if(linshi==-1)
				cout<<"Impossible";
			else
				cout<<linshi;
		}
		else
		{
			low=temp;
			high=heji+1;
			long long result=BinSear(heji,N2,low,high);
			
			if(result==-1)
				cout<<"Impossible";
			else
				cout<<result;
		}
	}
		
	if(tag==2)
	{
		heji=jinzhi(N2,radix);
		long long temp=(long long)maxstr(N1)+1;//此处temp最小值为2,最大值为36 
		if(heji<=temp)//如果了heji比temp还要小 
		{
			long long linshi=BinSear(heji,N1,temp,36);//待求进制数介于temp到36之间  
			if(linshi==-1)
				cout<<"Impossible";
			else
				cout<<linshi;
		}
		else
		{
			low=temp;
			high=heji+1;
			long long result=BinSear(heji,N1,low,high);
			if(result==-1)
				cout<<"Impossible";
			else
				cout<<result;
		}
	}
	return 0;
}

int compare(char str[],long long radix,long long target)
{
	int length=strlen(str);
	long long sum=0;
	for(int i=0;i<length;i++)
	{
		if(str[i]<58)
			sum=sum*radix+(str[i]-48);
		else
			sum=sum*radix+(str[i]-87);
		if(sum>target||sum<0)//sum<0是因为有可能目标数太大了,导致long long也不够存储,超过计算机存储范围,就会变为复数 
			return 1;
	}
	if(sum>target)
		return 1;
	else if(sum<target)
		return -1;	
	else
		return 0;//sum等于target 
}


long long BinSear(long long target,char str[],long long low,long long high)
{
	long long mid=low;
	while(low<=high)
	{
		if(compare(str,mid,target)==1)
			high=mid-1;
		else if(compare(str,mid,target)==-1)
			low=mid+1;
		else
			return mid;	
		mid=(low+high)/2;//缩小查找范围 
	}
	return -1;	
}
long long jinzhi(char str[],long long radix)
{
	int length=strlen(str);
	long long sum=0;
	for(int i=0;i<length;i++)
		if(str[i]<58)
		sum=sum*radix+(str[i]-48);
		else
		sum=sum*radix+(str[i]-87);
	return sum;	
} 
int maxstr(char str[])//进制最小数量必须所包含最大数字大1,例如出现有f,则至少是16进制,如出现7,至少是8进制 
{
	int length=strlen(str);
	int max=0;
	for(int i=0;i<length;i++)
	{
		if(str[i]<58&&str[i]-48>max)
		max=str[i]-48;
		else if(str[i]-87>max)
		max=str[i]-87;
	}
	if(max>1)
		return max;
	else
		return 1;//如果字符串内容全都是0,那么最大值应该是1才对 
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值