1010 Radix (25分)

Posted wsshub

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1010 Radix (25分)相关的知识,希望对你有一定的参考价值。

技术图片

 

这题值得一做。好题。20个测试点,吓死。第一次写13分,是没理解题意,修修补补得24分,第7个测试点没通过,必须要用二分查找。改用二分查找拿了满分。列一下需要注意的几个点(我把给出进制的数叫做基准数,让我们求出进制的数叫做所求数):

1.进制数最大不是36,进制数会非常非常大,可能超出int表示的范围,用long long。比如9,9是10进制数,也可能是10000进制数。

2.题目要求找到使得“所求数”和“基准数”相等的进制,这个进制,至少是“所求数”里最大的数字+1,这是所求进制的下界,如果这个进制下两数不相等,那么要继续往前找,上界怎么确定?第一,如果基准数比所求数大,那么上界是基准数+1,第二,如果基准数比所求数小,那么上界等于下界(即“所求数”里最大的数字+1)。上下界差距可能会非常大,我们想找到所求的最小进制,简单的思路是从下界遍历到上界,好像这是可以的,实际上,如果把上界设置到10000,可以拿到23分(第18和第7不会通过),但是,10000这个上界并不足够,也许18和7正是设置了某个非常大的数,但从小到大逐步遍历会超时严重,要用到二分查找来节省时间。可以用邓书上提到的二分查找改进版,找到使得所求数<=基准数的最大进制,最后判断在这个进制下的所求数是否和基准数相等来输出结果。

3.即使用了long long,在转化为10进制的过程中(不管几进制,都要转化为10进制比较大小),由于累加和乘积,有可能会溢出,溢出会出现循环,long long所能表示的最大值+1会变成long long所能表示的最小值(是和该最大值绝对值相等的负数)。要注意这个溢出的处理。

原本我按自己的思路实现拿了23分,也很简洁,开心。最后改了long long和二分查找就拿了满分(这个二分查找改进版的思路我想了很久才勉强理解...),说起来简单,实际上花了不少时间。23分代码折叠起来,满分代码可以展开:

23分:

技术图片
 1 #include<iostream>
 2 #include<string> 
 3 using namespace std;
 4 int convert(string x,int radix)//radix进制改成十进制 
 5 {
 6     int size=x.size();
 7     int sum=0,temp=1;
 8     char s=(char)87;
 9     for(int i=size-1;i>=0;i--)
10     {
11         if(x[i]>=97)
12            sum=sum+(x[i]-s)*temp;
13         else   
14            sum=sum+(x[i]-0)*temp;
15                   
16         temp=temp*radix;
17      } 
18      
19     return sum;
20 }
21 int convert_2(string x)//找到某数的进制radix 
22 {
23     char max=(char)47;
24     int size=x.size();
25     for(int i=0;i<size;i++)
26     {
27         if(x[i]>max)
28           max=x[i];
29      } 
30     int radix;
31     if((max-0)>9)
32        radix=max-(char)87+1;
33     else
34        radix=(max-0)+1; 
35     
36     return radix;
37     
38 }
39 int main(){  
40     string num[2];
41     int tag,radix;
42     cin>>num[0]>>num[1]>>tag>>radix;
43     int exm_num=convert(num[tag-1],radix);
44     
45     int pos;
46     (tag==1)?pos=1:pos=0;
47     int oth_rad=convert_2(num[pos]);
48     int oth_num;
49     while(oth_rad<=10000)//改成10000可以得23分
50     {
51         oth_num=convert(num[pos],oth_rad);
52         if(oth_num==exm_num)
53               {
54                   cout<<oth_rad;
55                   return 0;
56               }
57         else
58             oth_rad++;       
59      } 
60     
61     cout<<"Impossible";    
62     
63     
64         
65         
66     
67 return 0;
68 }
View Code

 

25分:

 1 #include<iostream>
 2 #include<string> 
 3 #define max(a,b) (a>b)?a:b
 4 using namespace std;
 5 long long convert(string x,int radix)//radix进制改成十进制 
 6 {
 7     int size=x.size();
 8     long long sum=0,temp=1;
 9     char s=(char)87;
10     for(int i=size-1;i>=0;i--)
11     {
12         if(x[i]>=97)
13            sum=sum+(x[i]-s)*temp;
14         else   
15            sum=sum+(x[i]-0)*temp;
16         
17         temp=temp*radix;
18         if(sum<0||temp<0)
19            return -1;
20      }      
21     return sum;
22 }
23 long long convert_2(string x)//找到某数的进制radix 
24 {
25     char max=(char)47;
26     int size=x.size();
27     for(int i=0;i<size;i++)
28     {
29         if(x[i]>max)
30           max=x[i];
31      } 
32     long long radix;
33     if((max-0)>9)
34        radix=max-(char)87+1;
35     else
36        radix=(max-0)+1; 
37     
38     return radix;    
39 }
40 int main(){  
41     string num[2];
42     int tag;
43     long long radix;
44     cin>>num[0]>>num[1]>>tag>>radix;
45     long long exm_num=convert(num[tag-1],radix);
46     
47     int pos;
48     (tag==1)?pos=1:pos=0;
49     long long oth_rad=convert_2(num[pos]);//找到所求数的最小进制 
50     long long oth_num;
51     long long hi=max(exm_num+1,oth_rad)+1;//所求数可能的最大进制 
52     long long lo=oth_rad;   
53     while(lo<hi)
54     {    long long mid=(lo+hi)>>1;
55         oth_num=convert(num[pos],mid);
56         if(oth_num<0||oth_num>exm_num)
57            hi=mid;
58         else
59            lo=mid+1; 
60      }      
61      if(convert(num[pos],lo-1)==exm_num)
62         cout<<lo-1;
63      else
64         cout<<"Impossible";    
65    
66 return 0;
67 }

 

以上是关于1010 Radix (25分)的主要内容,如果未能解决你的问题,请参考以下文章

PAT 1010 Radix (25分) radix取值无限制,二分法提高效率

PAT 甲级 1010 Radix (25)(25 分)(听说要用二分,我没AC,之后再改)

1010 Radix (25分)

A1010 Radix (25 分)

PAT 甲级1010 Radix (25分)

1010 Radix (25 分)难度: 难 / 知识点: 二分查找