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


    为了便于自己复习,就将PAT的各题坑点罗列,以起到回顾反思之效。
    由于之前已经刷了一些题,这次就先从昨晚刚做的题开始。

    题意回顾:

    输入规格:给出 N1 N2 tag radix,N1和N2均不多余10个数字,每个数字取值范围是{0-9,a-z},a-z分别代表10-35。若tag=1,则radix代表N1的进制;若tag=2,则radix代表N2的进制。
    输出规格:若能寻一进制,使得N1==N2,则输出此进制;否则输出"Impossible"。若解不唯一,则输出解集中最小的进制。

    思路:

    此处假设tag==1。若N2只有一位数,比较N1的十进制和N2的大小,若相等,则要求寻找的进制有多解,最小解为N2+1;否则只有唯一解或无解,将N1、N2均转换成十进制进行比较大小,对要求寻找的进制采用二分法查找(时间复杂度为log(N))。

    个人坑点解析:

    1.要求寻找的那个进制不局限于2-36,所以二分法查找时右侧需设的很大,这里采用long long类型;
    2.long long类型的数据上限为2^63-1,在赋值给右边时,我尝试采用pow(2,63),结果溢出了,后采用0x7FFFFFFFFFFFFFFF,结果正确;
    3.二分法查找时,mid=(left+right)/2,注意left+right可能产生溢出现象,此处谨慎起见可以使right=0x7FFFFFFFFFFFFFFF-left;
    4.mid /=2时,个人建议使用位运算,即mid>>=2,算法效率将会比算术运算快很多很多,否则有可能产生超时(第七个测试点);
    5.在给left赋初值时不能从2开始!从你要求进制的那个数的最大dight数+1开始!否则测试点19会错误。

    代码:

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int number(char c)//计算一个digit的数字大小
    {
     if (c - '0' >= 0 && c - '0' <= 9)
     	 return c - '0';
     else
     	 return c - 'a' + 10;
    }
    long double compute(char c[], long long radix)//计算一个radix进制数的十进制大小
    {				
     int len = strlen(c);
     long double total = 0;
     for (int i = 0; i < len; i++)
     	 total += number(c[i])*pow(radix, len - i - 1);
     return total;
    }
    long long Radix(char c1[], char c2[], int radix)//数c1的进制为radix,计算c2的进制,若找不到一个进制使得c1==c2,返回-1
    {
     int c2_len = strlen(c2);
     if (c2_len == 1)//思路的分号前一句话的情况
     {
      if (compute(c1, radix) == number(c2[0]))
     	  return number(c2[0]) + 1;
      else
     	  return -1;
     }
     long double c1_num = compute(c1, radix);//以下是思路中所说的第二种情况,c1_num为c1十进制大小
     int max=0;
     for (int i = 0; i < c2_len; i++)
     	 if (number(c2[i]) > max)
       		max = number(c2[i]);
     long long left = max + 1, right = 0x7FFFFFFFFFFFFFFF - left, mid;//right赋此值防止mid溢出
     long double c2_num;//c2_num同
     while (left <= right)//二分法
     {
      mid = left + right;
      mid >>= 1;    //位运算效率奇高,尤其这么多次循环和这么大数字,“/=2”就太慢了
      c2_num = compute(c2, mid);
      if (c2_num > c1_num)
      	 right = mid - 1;
      else if (c2_num < c1_num)
       	left = mid + 1;
      else
      	 return mid;
     }
     return -1;
    }
    int main()
    {
     char N1[12], N2[12];
     int tag, radix;
     cin >> N1 >> N2 >> tag >> radix;
     long long red;
     if (tag == 1)
     	 red = Radix(N1, N2, radix);
     else
    	  red = Radix(N2, N1, radix);
     if (red == -1)
    	  cout << "Impossible";
     else
     	 cout << red;
     return 0;
    }

    以上是个人的解题思路,作者还是个大二萌新,不足之处还望有缘路过的大佬们批评指正。

  • 相关阅读:
    sql server 2008 R2突然用windows和sa都无法登录。昨天都还能登陆,今天突然不行。
    JSON
    String类型判断是否一致
    5-4利用选取事件实时修改订单
    5-3以复选框创建餐点选项
    mysql创建存储过程
    margin标记可以带一个、二个、三个、四个参数,各有不同的含义。
    CSS字间距
    Html合并单元格
    MySQL Innodb存储引擎 事务隔离级别 锁 理解
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12309123.html
Copyright © 2011-2022 走看看