您的位置:首页 > 其它

PAT 1010 Radix (25)

2015-06-30 22:01 357 查看
先看题目:



这个题目算是比较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才对
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: