zoukankan      html  css  js  c++  java
  • PAT 1010 Radix

    1010 Radix (25分)

    Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is yes, if 6 is a decimal number and 110 is a binary number.

    Now for any pair of positive integers N1 and N2, your task is to find the radix of one number while that of the other is given.

    Input Specification:

    Each input file contains one test case. Each case occupies a line which contains 4 positive integers:

    N1 N2 tag radix
    Here N1 and N2 each has no more than 10 digits. A digit is less than its radix and is chosen from the set { 0-9, a-z } where 0-9 represent the decimal numbers 0-9, and a-z represent the decimal numbers 10-35. The last number radix is the radix of N1 if tag is 1, or of N2 if tag is 2.

    Output Specification:

    For each test case, print in one line the radix of the other number so that the equation N1 = N2 is true. If the equation is impossible, print Impossible. If the solution is not unique, output the smallest possible radix.

    Sample Input 1:

    6 110 1 10
    Sample Output 1:
    2
    Sample Input 2:
    1 ab 1 2
    Sample Output 2:
    Impossible
     
    时间限制: 400 ms
    内存限制: 64 MB
    代码长度限制: 16 KB
     
     

    思路

    这题的有非常多坑。
    坑点:
    假设输入为 a b 1 radix ,根据题意,此时就要求使得a=b时,b的基数r :
    1. a, b有字母a-z,所以应该用string表示这两个数,数最长为10位,所以int范围不够,比如10个z,所以a或b对应的十进制数据类型应该为long long。

    2. r不一定是2-36,就比如8可以是九进制也可以是十进制,所以就要确定r的范围:

     r的下界肯定是b中最大那一位+1,就比如158至少是9进制。

       r的上界肯定不超过待比较的数对应的十进制数值,比如150 11251240 1 10,结果肯定不可能比150还大,

       但是有一种特殊情况,比如8 8 1 10,运行结果就应该是9,

       所以r的上界应该是(a)10+1,(a)10表示a对应的十进制的值

     因为(a)10是long long类型,可能不止十位数,所以使用顺序查找肯定会超时,这里已知上下界了,因此要使用二分查找。

    3. 但是采用二分法查找的时候,比如150 11251240 1 10,结果肯定不可能比150还大,但是二分mid为75的时候,有可能算出来的数已经大于long long的范围,已经溢出了,怎么处理溢出呢?溢出之后会变成最大负数,比如四位有符号数(计算机里面是补码表示) 的最大值是0111,也就是7,当大于7的时候就会溢出变成负数,比如为8时,就是1000,注意这里是补码,1000就是-8。那么只要是取值为负的,全部是上溢,说明基数取得过大了, 此时二分的时候就要往左边那一半找。

    (经过大量提交,可以得出结论:题目中给出测试点的已知基数不会溢出)

      

    结合以上分析,参考了网上许多大神的代码,终于是通过了,只能说这道题看似简单,但是想拿全部 25分,有难度。 

     
      1 #include <iostream>
      2 #include <stdio.h> 
      3 #include <string>
      4 
      5 using namespace std;
      6 
      7 // 获取每一位数的字符转成数字的值 
      8 long long getDigitValue(char n)
      9 {
     10     if(n >= '0' && n <= '9')
     11         return n-'0';
     12         
     13     // a-z 对应 10-35 
     14     if(n >= 'a' && n <= 'z')    
     15         return n-'a' + 10;    
     16         
     17     return -1;
     18 } 
     19 
     20 // 把radix进制转为十进制 
     21 long long toDecimal(string num, long long radix)
     22 {
     23     long long sum = 0;
     24     long long k = 1;
     25     long long i = num.length()-1;
     26     for(; i >= 0; --i)
     27     {
     28         long long val = getDigitValue(num[i]);
     29         sum += val * k;
     30         k *= radix;
     31     }
     32     
     33     return sum;
     34 }
     35 
     36 int main()
     37 {
     38     string a, b;
     39     long long tag, radix;
     40     cin >> a >> b >> tag >> radix;
     41     
     42     if(tag == 1)
     43     {
     44         long long decimal_a = toDecimal(a, radix); 
     45         long long left = getDigitValue(b[0]);
     46         for(long long i = 1; i < b.length(); ++i)
     47         {
     48             long long val = getDigitValue(b[i]);
     49             if(val > left)
     50                 left = val;
     51         }
     52         // 基数的下界是最大的那个数字加上1
     53         // 就比如158肯定不能是8进制,至少是9进制 
     54         left += 1;    
     55         
     56         // 基数的上界是另一个要比较的数字+1(这里就是decimal_a+1) 
     57         // 另一个要比较的数字(比如10个z)可能超出int范围,所以这里要用long long
     58         long long right = decimal_a+1; 
     59         // 二分查找 
     60         while(left <= right)
     61         {
     62             int mid = (left+right)/2;
     63             long long decimal_b = toDecimal(b, mid);
     64             if(decimal_a == decimal_b)
     65             {
     66                 cout << mid;
     67                 return 0;
     68             }
     69             else if(decimal_a < decimal_b || decimal_b < 0)
     70                 right = mid-1;
     71             else
     72                 left = mid+1;
     73         } 
     74     }
     75     else
     76     {
     77         long long decimal_b = toDecimal(b, radix);
     78         
     79         long long left = getDigitValue(a[0]);
     80         for(long long i = 1; i < a.length(); ++i)
     81         {
     82             long long val = getDigitValue(a[i]);
     83             if(val > left)
     84                 left = val;
     85         }
     86         left += 1;    
     87         
     88         long long right = decimal_b+1; 
     89         // 二分查找 
     90         while(left <= right)
     91         {
     92             long long mid = (left+right)/2;
     93             long long decimal_a = toDecimal(a, mid);
     94             if(decimal_a == decimal_b)
     95             {
     96                 cout << mid;
     97                 return 0;
     98             }
     99             else if(decimal_b < decimal_a || decimal_a < 0)
    100                 right = mid-1;
    101             else
    102                 left = mid+1;
    103         } 
    104     }
    105         
    106     cout << "Impossible";
    107     
    108     return 0;
    109 }
  • 相关阅读:
    基于Ubuntu Jeos打造自己的精简版Linux服务器
    35 vs 53怎么裁
    父母在,不远游
    linux deepin是基于linux mint修改
    novell
    Sahi
    virtualbox on windows store vdi on ndfs due the file will bigger than 4gb
    在Linux下配置邮件系统
    CSS3 backgroundsize 属性
    dede:list及dede:arclist 按权重排序的方法
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/12601356.html
Copyright © 2011-2022 走看看