PAT (Advanced Level) Practice 1010 Radix PAT甲级最低通过率,果然名不虚传

在这里插入图片描述
Radix PAT Advanced Level上面通过率最低的一题了。果然有很多坑
分析:

  1. 看到题目中0~z,很容易想象是36进制,然而实际上进制上不封顶,我们只有搜索,而一般的搜索会超时 改为二分搜索
  2. 这道题用int肯定不行的 某些情况用long long int还是会溢出,变成负数,这里要追加判断

思路:

  1. 题目给定了一个确定的数,先把它转换成10进制
  2. 二分搜索,确认左边界右边界,左边界为另一个人串的最大数字+1(小于2则为2) 右边界一直到已经确定的数,如下情况在这里插入图片描述

这题卡了我很多时间的地方是,我没有把全部类型转化为long long int,也就是说某些地方我用long long int 与int相乘了,这种情况在数据小的时候没问题,但是一旦超过int的上限,那么int就变成了负数,这样相乘就是错的

以后千万要注意类型相乘相加!!!!
最终AC代码

参考了 https://blog.csdn.net/linghugoolge/article/details/82620905

#include<iostream>
#include<cstdio>
#include<cmath>
#define LL long long int
using namespace std;
//任意进制转化为十进制 
LL ToTen(string s,int k)
{
	LL sum=0;
	LL p=1;
	//处理进制数 变为10进制 
	for(int i=s.size()-1;i>=0;i--)
	{
		if(s[i]>='0'&&s[i]<='9')
			sum+=(s[i]-'0')*p;		
		else sum+=(s[i]-'a'+10)*p;
		p*=k;
	}
	return sum;
}
LL getMax(string s)
{
	LL max=0;
	for(int i=s.size()-1;i>=0;i--)
	{
		if(s[i]>='0'&&s[i]<='9')
			if((s[i]-'0')>max)max=s[i]-'0';		
		if(s[i]>='a'&&s[i]<='z')
			if(s[i]-'a'+10>max)max=s[i]-'a'+10;
	}
	return max+1;
}
LL findRadix(LL target,string str,LL L,LL R)
{
	LL tmp=0;
	while(L<=R)
	{
		LL mid=(L+R)/2;
		tmp=ToTen(str,mid);
		if(tmp==target) return mid;
		else if(tmp<0||tmp>target) R=mid-1;
		else if(tmp<target) L=mid+1;
		
	}
	return -1;
}
int main()
{
	string str1,str2;
	int tag,radix;
	cin>>str1>>str2>>tag>>radix;
	if(tag==2)swap(str1,str2); 
	//先处理一个给定的数字,将它转换为10进制 
	//用二分搜索法依次处理另一个数字,转换为十进制
	LL tn1;
	tn1=ToTen(str1,radix);
	//寻找左边界 这里可能小于2 要改为2进制 
	LL left=getMax(str2);
	left=left>2?left:2;
	//寻找右边界
	LL right=max(tn1,left); 
	//tn1>left?tn1:left
	LL ans=findRadix(tn1,str2,left,right);
	if(ans==-1)cout<<"Impossible";
	else cout<<ans;
	return 0;
} 

初步代码,7和10测试点没有通过

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long 
using namespace std;
//任意进制转化为十进制 
int maxJ=1000;
LL ToTen(string s,int k)
{
	LL sum=0;
	int p=1;
	//处理进制数 变为10进制 
	for(int i=s.size()-1;i>=0;i--)
	{
		if(s[i]>='0'&&s[i]<='9')
			sum+=(s[i]-'0')*p;		
		else sum+=(s[i]-'a'+10)*p;
		p*=k;
	}
//	cout<<sum;
	return sum;
}
int getMax(string s)
{
	int max=0;
	for(int i=s.size()-1;i>=0;i--)
	{
		if(s[i]>='0'&&s[i]<='9')
			if((s[i]-'0')>max)max=s[i]-'0';		
		if(s[i]>='a'&&s[i]<='z')
			if(s[i]-'a'+10>max)max=s[i]-'a'+10;
//		cout<<"max:"<<max<<endl;
	}
	return max;
}

int main()
{
	string n1,n2;
	int tag,radix;
	cin>>n1>>n2>>tag>>radix;
	//先处理一个给定的数字,将它转换为10进制 
	//从2进制到36进制依次处理另一个数字,转换为十进制
	//判断是否相等 
	int cn1=0;
	int cn2=0;	
	LL tn1=0;
	LL tn2=0;
	if(tag==1)
	{
		//确认了一个数 
		tn1=ToTen(n1,radix);
		int lim=getMax(n2);
//		cout<<lim<<endl;
		for(int i=lim+1>2?lim+1:2;i<=maxJ;i++)
		{
			LL tmp=ToTen(n2,i);
			if(tmp<0)
			{
				cout<<"Impossible";
				return 0;
			}
			if(tmp==tn1)
			{
				cout<<i;
				return 0;
			} 
		}
	}
	else
	{
		tn2=ToTen(n2,radix);
		int lim=getMax(n1);
		for(int i=lim+1>2?lim+1:2;i<=maxJ;i++)
		{
			LL tmp=ToTen(n1,i);
			if(tmp<0)
			{
				cout<<"Impossible";
				return 0;
			}
			if(tmp==tn2)
			{
				cout<<i;
				return 0;
			}

		}
	}
	
	cout<<"Impossible";
	return 0;
	
} 

改进后的代码 case10始终有错 改得我要吐血了,真的看不出来哪里出问题了…
终于排查出来了,在二分搜索和getMax函数我应该返回LL,最致命的错误是,二分搜索里面的mid我设置为int型,导致case10一直报错,改为LL就好了 真坑啊,以后类型转换千万要注意

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long int
using namespace std;
//任意进制转化为十进制 
int maxJ=1000;
LL ToTen(string s,int k)
{
	LL sum = 0;
	for (int i = 0; i < s.length(); ++i) {
		if (isdigit(s[i]))
			sum = sum*k+s[i] - '0';
		else if (isalpha(s[i]))
			sum = sum*k+s[i] - 'a'+10;
	}
	return sum;
}
int getMax(string s)
{
	int max=0;
	for(int i=s.size()-1;i>=0;i--)
	{
		if(s[i]>='0'&&s[i]<='9')
			if((s[i]-'0')>max)max=s[i]-'0';		
		if(s[i]>='a'&&s[i]<='z')
			if(s[i]-'a'+10>max)max=s[i]-'a'+10;
	}
	return max+1;
}
int findRadix(LL target,string str,LL L,LL R)
{
	LL tmp=0;
	while(L<=R)
	{
		int mid=(L+R)/2;
		tmp=ToTen(str,mid);
		if(tmp==target) return mid;
		else if(tmp<0||tmp>target) R=mid-1;
		else if(tmp<target) L=mid+1;
		
	}
	return -1;
}
int main()
{
	string str1,str2;
	int tag,radix;
	cin>>str1>>str2>>tag>>radix;
	if(tag==2)swap(str1,str2); 
	//先处理一个给定的数字,将它转换为10进制 
	//用二分搜索法依次处理另一个数字,转换为十进制
	LL tn1;
	tn1=ToTen(str1,radix);
	//寻找左边界 这里可能小于2 要改为2进制 
	LL left=getMax(str2);
	left=left>2?left:2;
	//寻找右边界
	LL right=max(tn1,left); 
	//tn1>left?tn1:left
	LL ans=findRadix(tn1,str2,left,right+1);
	if(ans==-1)cout<<"Impossible";
	else cout<<ans;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值