PAT 1010 Radix (25分) radix取值无限制,二分法提高效率
题目
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
题目解读
给出两个数N1,N2,给出其中一个数N1或N2的进制(输入数据中tag=1表示这这是给出的是N1的进制,tag=2表示给出的是N2的进制),为第二个数寻找合适的进制,使得 两者转换成10进制后的结果相等。输出找到的radix,如果不存在这样的进制,那就输出 ”Impossible“
N1和N2的长度最多为10,每个位置上的数字可以是 0-9 或 a-z,其中 a-z数字 10-35
注意:
- 每个数长度最多为
10,每个位置大小都可以是0-35,那么int肯定是不够存的,比如这个数是zzzzzzzzzz,35 ^ 9 > 2 ^ 32,我们用long long - 并未从题中看出来radix的取值范围(不要自己觉得它最大是35),所以也要定义成
long long才保险。
思路分析
相信大家都能想到的是,先把给出的N1或N2(假设给出的进制是N1的进制)按照给出的进制转成十进制,然后从1开始测试每种进制,把N2转成十进制判断是否和N1相等,如不相等就增加进制,继续转换,比较。。。
问题是,如果这个进制存在还好说,我从1开始增加,总能找到那个进制;但是如果它不存在呢?增加到无穷大程序都跑不完。。。。
所以我们必须先确定radix的上限和下限。
(以第一个数进制给出,转换成十进制结果是N1,求N2的进制为例进行说明)
- 假如
N2每个位置上的数字中最大的那个是x,那么N2的进制最小是x + 1,比如你某个位置是0-9,最起码得是10进制吧。
那么它的进制的最大值是多少呢??那么这个进制最大为
N1为什么???
假如
N2只有一位数,假设为x,那么你的进制可以是 比这个数本身大的 任意数字,它所代表的值是 x * 进制 0 = x,所以除非x和N1相等,否则你取啥进制都没办法。假如
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都存不下了。
while(low <= high) {
long long mid = low + (high - low) / 2;
long long temp = convert(numStr, mid);
// temp < 0,代表得到的数字越界,temp > target都代表当前进制太大,需要调整上限
if (temp < 0 || temp > target) high = mid - 1;
// 当前进制正好
else if (temp == target) return mid;
// 当前进制太小
else low = mid + 1;
}
完整代码
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
/**
* 给出两个数n1,n2,给出其中一个数n1及其进制radix,为第二个数寻找合适的进制使得 两者相等
*
* 首先,每个数长度最多为10,每个位置大小都可以是0-35,那么int肯定是不够存的,比如这个数是zzzzzzzzzz,35 ^ 9 > 2 ^ 32
*
* 加入这个数每个位置上的数字中最大的那个是 x ,那么这个数的【进制最小是 x + 1】,比如你要表示0-9,最起码得是10进制吧
* 那么它的进制的最大值是多少呢??其实这个是没有限制的,你可以是任意进制,所以我们用了long long来存
*
* 但在这个题中,必须要有一个合适的进制使得n2能转为n1,那么这个【进制最大为 n1】
*
* 为什么???
*
* 假如n2只有一位,那么你的进制只要比这个数字大,就可以任意取,随意,但除非你本身和n1相等,否则你取啥进制都没办法,
* 因为最后一个位置是最低位,它代表的是 进制 ^ 0 = 1
*
* 假如n2有两位,那它最小也就是 10,1 * 进制 + 0 * 进制 ^ 0 = 进制,
* 所以n2的大小就等于进制的大小,如果你让n2的进制=n1时,n2都不能和n1相等,那么你把进制变得更大,n2就更不可能转为n1
* 当n2有更多位时就更不用说了,肯定更不可能,每差一个位置,值就差的更多
*
* 所以这个进制的取值范围是 【n2字符串中最大的那个字符代表的值+1,n1】,接着利用二分法
*
*/
// 根据进制,把字符串转为实际数字
long long convert(string numStr, long long radix) {
long long res = 0;
int exp = 0; // 最低位指数为0
// auto自动判断类型,rbegin()是最后一个字符,rend()是第一个字符
for (auto it = numStr.rbegin(); it != numStr.rend(); ++it) {
// '0'-'9',注意这里要加*才能得到值
if (isdigit(*it))
res += (*it - '0') * pow(radix, exp++);
// 'a'-'z'
else
res += (*it - 'a' + 10) * pow(radix, exp++);
}
// 返回结果
return res;
}
// 找到合适的进制,使得numStr在这个进制下 == target
long long findRadix(string numStr, long long target) {
// 找到字符串形式的n2中最大的那个字符,注意这里要加*才能得到值
char maxChar = *max_element(numStr.begin(), numStr.end());
// 转为数字加1,就是 进制的下限
long long low = (isdigit(maxChar) ? maxChar - '0' : maxChar - 'a' + 10) + 1;
// 进制的上限就是 n1
long long high = max(low, target);
// 二分法
while(low <= high) {
long long mid = low + (high - low) / 2;
long long temp = convert(numStr, mid);
// temp < 0,代表得到的数字越界,temp > target都代表当前进制太大,需要调整上限
if (temp < 0 || temp > target) high = mid - 1;
// 当前进制正好
else if (temp == target) return mid;
// 当前进制太小
else low = mid + 1;
}
// 没找到合适的,返回-1
return -1;
}
int main() {
// 两个数,每个位置是0-9或a-z,a-z代表10-35,每个数最多长度为10,如果是35进制,最大为35 * 35 ^ 9, 大于2^32
string n1, n2;
// radix,基数(进制),tag为1代表这个基数针对于第一个数字,tag为2代表这个基数针对第2个数字
int tag;
long long radix;
cin >> n1 >> n2 >> tag >> radix;
long long res = tag == 1 ? findRadix(n2, convert(n1, radix)) : findRadix(n1, convert(n2, radix));
// 不存在这样的进制
if (res == -1)
cout << "Impossible";
else
cout << res;
return 0;
}
PAT 1010 Radix (25分) radix取值无限制,二分法提高效率的更多相关文章
- PAT Advanced 1010 Radix(25) [⼆分法]
题目 Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The ...
- 1010 Radix (25 分)
Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The an ...
- PAT 1029 Median (25分) 有序数组合并与防坑指南
题目 Given an increasing sequence S of N integers, the median is the number at the middle position. Fo ...
- 【PAT甲级】1010 Radix (25 分)(二分)
题意: 输入两个数可能包含小写字母,1或者2,进制大小.第三个数为代表第一个数是第四个数进制的,求第二个数等于第一个数时进制的大小,不可能则输出Impossible,第三个数为2代表第二个数是第四个数 ...
- 1010 Radix (25 分),PTA
题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536 题意:给定n1.n2两个数,求可以是两 ...
- 1010 Radix (25分)
改了一天也没明白,第7个数据是怎么卡的 #include <bits/stdc++.h> using namespace std; const int maxn=1005; typedef ...
- A1010 Radix (25 分)
一.技术总结 首先得写一个进制转换函数convert(),函数输入参数是字符串str和需要转化的进制(使用long long数据类型).函数内部知识,使用函数迭代器,即auto it = n.rbeg ...
- 7-19 PAT Judge(25 分)
The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...
- PAT A1075 PAT Judge (25 分)——结构体初始化,排序
The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...
随机推荐
- 小白必看,Python 各种下划线都是啥意思_、_xx、xx_、__xx、__xx__、_classname_
我们在定义一些变量或者方法的时候,常常会用到下划线,在 Python 中,下划线可是很有用处的哟,比如变量,有些是一个下划线开头的(_xx),有些是两个下划线开头的(__xx),有些是在名称的结尾添加 ...
- 尤雨溪的vue怎么学,应该从vue-cli开始,为什么?
带手机验证码登陆, 带全套购物车系统 带数据库 前后端分离开发 带定位用户功能 数据库代码为本地制作好了 带支付宝支付系统 带django开发服务器接口教程 地址: https://www.dua ...
- 【shell】Shell变量基础及深入
1. 什么是变量 变量就是用一个固定的字符串(也可能是字符数字等的组合),替代更多更复杂的内容,这个内容里可能还会包含变量和路径,字符串等其他内容. 变量的定义是存在内存中. x=1 y=2 2. 变 ...
- 腾讯视频怎么转成mp4模式 软件 工具 方法 最新【已解决】
1.搜索: 小白兔视频格式在线转换 2.转换好后视频已经是MP4格式了. 转载于:https://blog.51cto.com/14204019/2396896
- Crash日志解析
当应用程序崩溃时,会创建一个崩溃报告,这对于了解导致崩溃的原因非常有用.本文档包含有关如何表示,理解和解释崩溃报告的基本信息. 1.介绍 2.获取崩溃和低内存报告 3.象征性的奔溃报告 1.位码(bi ...
- LinearLayout控件
LinearLayout是线性布局控件,它包含的子控件将以横向或竖向的方式排列,按照相对位置来排列所有的widgets或者其他的containers,超过边界时,某些控件将缺失或消失.因此一个垂直列表 ...
- 跟风微信小程序,生鲜水果店如何借力小程序每天多赚2万块?
公司旁边的水果店,虽然是一家实体店,但老板有一颗爱玩互联网的心. 老板非常重视线上的营销推广,什么新的线上推广方式都爱尝试一下.公众号大热时做了自己的微信公众号,并且有自己的微信商城,不过线上的销售一 ...
- RedHat Enterprise Linux 5.8 升级openssl
RedHat Enterprise Linux 5.8升级openssl,遇到以下问题,做下标记: 由于之前安装RedHat Enterprise Linux 5.8 时候只安装了服务器环境,没有安装 ...
- 数学--数论--POJ281(线性同余方程)
埃琳娜(Elina)正在阅读刘如家(Rujia Liu)写的书,其中介绍了一种表达非负整数的奇怪方法.方式描述如下: 选择k个不同的正整数a 1,a 2,-,a k.对于一些非负米,把它由每一个我(1 ...
- ubuntu 和 centos 如何区分系统
Ubuntu Ubuntu有着漂亮的用户界面,完善的包管理系统,强大的软件源支持,丰富的技术社区,Ubuntu还对大多数硬件有着良好的兼容性,包括最新的图形显卡等等.这一切让Ubuntu越来越向大众化 ...