题目

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 N​1​​ and N​2​​ , 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

题目解读

给出两个数N1,N2,给出其中一个数N1或N2的进制(输入数据中tag=1表示这这是给出的是N1的进制,tag=2表示给出的是N2的进制),为第二个数寻找合适的进制,使得 两者转换成10进制后的结果相等。输出找到的radix,如果不存在这样的进制,那就输出 ”Impossible

N1N2的长度最多为10,每个位置上的数字可以是 0-9a-z,其中 a-z数字 10-35

注意:

  • 每个数长度最多为10,每个位置大小都可以是0-35,那么int肯定是不够存的,比如这个数是zzzzzzzzzz35 ^ 9 > 2 ^ 32,我们用 long long
  • 并未从题中看出来radix的取值范围(不要自己觉得它最大是35),所以也要定义成 long long才保险。

思路分析

相信大家都能想到的是,先把给出的N1N2(假设给出的进制是N1的进制)按照给出的进制转成进制,然后从1开始测试每种进制,把N2转成进制判断是否和N1相等,如不相等就增加进制,继续转换,比较。。。

问题是,如果这个进制存在还好说,我从1开始增加,总能找到那个进制;但是如果它不存在呢?增加到无穷大程序都跑不完。。。。

所以我们必须先确定radix的上限和下限

(以第一个数进制给出,转换成十进制结果是N1,求N2的进制为例进行说明)

  • 假如N2每个位置上的数字中最大的那个是 x ,那么N2的进制最小是 x + 1,比如你某个位置是0-9,最起码得是10进制吧。
  • 那么它的进制的最大值是多少呢??那么这个进制最大为 N1

    为什么???

    假如N2只有一位数,假设为x,那么你的进制可以是 比这个数本身大的 任意数字,它所代表的值是 x * 进制 0 = x,所以除非xN1相等,否则你取啥进制都没办法。

    假如N2有两位,那它最小也就是 '1 0',代表的值是 1 * 进制 1 + 0 * 进制 0 = 进制,所以N2的大小就等于进制的大小,如果你让N2的进制=N1时,N2都不能和N1相等,那么你把进制变得更大,N2转换后必然比N1更大。当N2有更多位时就更不用说了,肯定更不可能,每差一个位置,值就差的更多

  • 所以N2进制的取值范围【N2字符串中最大的那个字符代表的值+1,N1】

确定了进制的取值范围之后,我们可以用for循环进行遍历,但是复杂度比较高,这里我们选取二分法

注意不要漏掉对溢出情况的判断,若N2在某进制下转换成十进制的结果大于N1,应该缩小右边界;但是,如果N2在某进制下转换成十进制的结果小于0,也要缩小右边界小于0说明进制太大,它转换后long long都存不下了。

  1. while(low <= high) {
  2. long long mid = low + (high - low) / 2;
  3. long long temp = convert(numStr, mid);
  4. // temp < 0,代表得到的数字越界,temp > target都代表当前进制太大,需要调整上限
  5. if (temp < 0 || temp > target) high = mid - 1;
  6. // 当前进制正好
  7. else if (temp == target) return mid;
  8. // 当前进制太小
  9. else low = mid + 1;
  10. }

完整代码

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cmath>
  4. using namespace std;
  5. /**
  6. * 给出两个数n1,n2,给出其中一个数n1及其进制radix,为第二个数寻找合适的进制使得 两者相等
  7. *
  8. * 首先,每个数长度最多为10,每个位置大小都可以是0-35,那么int肯定是不够存的,比如这个数是zzzzzzzzzz,35 ^ 9 > 2 ^ 32
  9. *
  10. * 加入这个数每个位置上的数字中最大的那个是 x ,那么这个数的【进制最小是 x + 1】,比如你要表示0-9,最起码得是10进制吧
  11. * 那么它的进制的最大值是多少呢??其实这个是没有限制的,你可以是任意进制,所以我们用了long long来存
  12. *
  13. * 但在这个题中,必须要有一个合适的进制使得n2能转为n1,那么这个【进制最大为 n1】
  14. *
  15. * 为什么???
  16. *
  17. * 假如n2只有一位,那么你的进制只要比这个数字大,就可以任意取,随意,但除非你本身和n1相等,否则你取啥进制都没办法,
  18. * 因为最后一个位置是最低位,它代表的是 进制 ^ 0 = 1
  19. *
  20. * 假如n2有两位,那它最小也就是 10,1 * 进制 + 0 * 进制 ^ 0 = 进制,
  21. * 所以n2的大小就等于进制的大小,如果你让n2的进制=n1时,n2都不能和n1相等,那么你把进制变得更大,n2就更不可能转为n1
  22. * 当n2有更多位时就更不用说了,肯定更不可能,每差一个位置,值就差的更多
  23. *
  24. * 所以这个进制的取值范围是 【n2字符串中最大的那个字符代表的值+1,n1】,接着利用二分法
  25. *
  26. */
  27. // 根据进制,把字符串转为实际数字
  28. long long convert(string numStr, long long radix) {
  29. long long res = 0;
  30. int exp = 0; // 最低位指数为0
  31. // auto自动判断类型,rbegin()是最后一个字符,rend()是第一个字符
  32. for (auto it = numStr.rbegin(); it != numStr.rend(); ++it) {
  33. // '0'-'9',注意这里要加*才能得到值
  34. if (isdigit(*it))
  35. res += (*it - '0') * pow(radix, exp++);
  36. // 'a'-'z'
  37. else
  38. res += (*it - 'a' + 10) * pow(radix, exp++);
  39. }
  40. // 返回结果
  41. return res;
  42. }
  43. // 找到合适的进制,使得numStr在这个进制下 == target
  44. long long findRadix(string numStr, long long target) {
  45. // 找到字符串形式的n2中最大的那个字符,注意这里要加*才能得到值
  46. char maxChar = *max_element(numStr.begin(), numStr.end());
  47. // 转为数字加1,就是 进制的下限
  48. long long low = (isdigit(maxChar) ? maxChar - '0' : maxChar - 'a' + 10) + 1;
  49. // 进制的上限就是 n1
  50. long long high = max(low, target);
  51. // 二分法
  52. while(low <= high) {
  53. long long mid = low + (high - low) / 2;
  54. long long temp = convert(numStr, mid);
  55. // temp < 0,代表得到的数字越界,temp > target都代表当前进制太大,需要调整上限
  56. if (temp < 0 || temp > target) high = mid - 1;
  57. // 当前进制正好
  58. else if (temp == target) return mid;
  59. // 当前进制太小
  60. else low = mid + 1;
  61. }
  62. // 没找到合适的,返回-1
  63. return -1;
  64. }
  65. int main() {
  66. // 两个数,每个位置是0-9或a-z,a-z代表10-35,每个数最多长度为10,如果是35进制,最大为35 * 35 ^ 9, 大于2^32
  67. string n1, n2;
  68. // radix,基数(进制),tag为1代表这个基数针对于第一个数字,tag为2代表这个基数针对第2个数字
  69. int tag;
  70. long long radix;
  71. cin >> n1 >> n2 >> tag >> radix;
  72. long long res = tag == 1 ? findRadix(n2, convert(n1, radix)) : findRadix(n1, convert(n2, radix));
  73. // 不存在这样的进制
  74. if (res == -1)
  75. cout << "Impossible";
  76. else
  77. cout << res;
  78. return 0;
  79. }

PAT 1010 Radix (25分) radix取值无限制,二分法提高效率的更多相关文章

  1. PAT Advanced 1010 Radix(25) [⼆分法]

    题目 Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The ...

  2. 1010 Radix (25 分)

    Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The an ...

  3. PAT 1029 Median (25分) 有序数组合并与防坑指南

    题目 Given an increasing sequence S of N integers, the median is the number at the middle position. Fo ...

  4. 【PAT甲级】1010 Radix (25 分)(二分)

    题意: 输入两个数可能包含小写字母,1或者2,进制大小.第三个数为代表第一个数是第四个数进制的,求第二个数等于第一个数时进制的大小,不可能则输出Impossible,第三个数为2代表第二个数是第四个数 ...

  5. 1010 Radix (25 分),PTA

    题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536 题意:给定n1.n2两个数,求可以是两 ...

  6. 1010 Radix (25分)

    改了一天也没明白,第7个数据是怎么卡的 #include <bits/stdc++.h> using namespace std; const int maxn=1005; typedef ...

  7. A1010 Radix (25 分)

    一.技术总结 首先得写一个进制转换函数convert(),函数输入参数是字符串str和需要转化的进制(使用long long数据类型).函数内部知识,使用函数迭代器,即auto it = n.rbeg ...

  8. 7-19 PAT Judge(25 分)

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...

  9. PAT A1075 PAT Judge (25 分)——结构体初始化,排序

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...

随机推荐

  1. Github第三方登录

    笔者第一次写网站只写了接收参数以及登录页面就兴奋了一整天,还特意地加上了第三方登录,想起当时的情景还历历在目.之前是照着被人的博客一步步完成第三方登录的功能,现在就要自己来理解完成了 1. OAuth ...

  2. java之 惰性初始化

    class Soap { private String s; Soap(){ System.out.println("Soap()"); s="Constructed&q ...

  3. vue2.x学习笔记(二十四)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12663909.html. 插件 插件通常是用来为vue添加全局功能的. 插件的功能范围 插件的功能范围没有严格的限 ...

  4. Java初学者最近三次作业的心得体会

    作为一个初学者,简单的谈一下自己的作业心得体会.如果你是完全没有接触过Java的学习,本篇博文可能会有些收获,如果你已经学习Java有一段时间了,那么可以放弃这篇文章了,因为这篇文章讲解的是基本的东西 ...

  5. 删除集群mds

    2019独角兽企业重金招聘Python工程师标准>>> 删除cephfs文件系统步骤: 1.停掉服务端mds: #systemctl stop {mds_service} 2.将md ...

  6. RAID、LVM和btrfs文件系统

    一.RAID: Redundant Arrays of Inexpensive Disks,廉价磁盘冗余阵列: Redundant Arrays of Independent Disks,独立磁盘冗余 ...

  7. C++课程设计,12306模拟写起来就是这么粗暴

    这篇文章很详细,也很多希望可以好好看看!看完C++稳过! 一.12306应该具备那些功能 1.查询(一个月以内的): 1.查车票:出发地+目的地+出发时间->显示经过两站车票信息 (余票,车次信 ...

  8. 单源最短路径:Dijkstra算法(堆优化)

    前言:趁着对Dijkstra还有点印象,赶快写一篇笔记. 注意:本文章面向已有Dijkstra算法基础的童鞋. 简介 单源最短路径,在我的理解里就是求从一个源点(起点)到其它点的最短路径的长度. 当然 ...

  9. muduo网络库源码学习————线程类

    muduo库里面的线程类是使用基于对象的编程思想,源码目录为muduo/base,如下所示: 线程类头文件: // Use of this source code is governed by a B ...

  10. Nginx模块开发(1)————类helloworld

    Nginx看了一点了,准备写个helloworld试试,觉得只看书的话很多东西都乱乱的,晕晕的,印象不深. 我的helloworld模块的目的就是:能够在浏览器里输入http://你的ip地址/lcw ...