【PAT甲级 - C++题解】1010 Radix

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1010 Radix (pintia.cn)
🔑中文翻译:进制
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1010 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
题意

N 1 N1 N1 N 2 N2 N2 是两个不超过 10 10 10 位的数字,radix 是其中一个数字的进制,如果 tag 1 1 1,则 radix N 1 N1 N1 的进制,如果 tag 2 2 2,则 radix N 2 N2 N2 的进制。

输出使得 N 1 = N 2 N1=N2 N1=N2 成立的另一个数字的进制数。

如果等式不可能成立,则输出 Impossible

如果答案不唯一,则输出更小的进制数。

思路

这道题涉及到了秦九韶算法:

假设给定一个 d 进制 abc ,那么我要转化成十进制的公式为: a ∗ d 2 + b ∗ d 1 + c a*d^2+b*d^1+c ad2+bd1+c ,放到循环中其实就是:

//假设n为字符串
long long res = 0;
for(auto x : n)
	res = res * d + x - '0';

具体步骤:

  1. 先对输入的参数进行统一化操作,如果 t a g = = 2 tag==2 tag==2 就交换 n 1 n1 n1 n 2 n2 n2 ,因为后续的操作都是对 n 1 n1 n1 取十进制 t a r g e t target target ,然后去找 n 2 n2 n2 的进制。
  2. 由于 n 2 n2 n2 的进制是不固定的,它可以超过 36 36 36 进制,所以有可能会非常大,例如 n 1 n1 n1 的十进制为 88 88 88 ,则 n 2 n2 n2 假如是 10 10 10 则最大进制就可以取到 88 88 88 。另外,当 n 2 n2 n2 位数为 1 1 1 时,其进制数就至少要取到 36 36 36 ,因为当位数为 1 1 1 时,其最大数为 z z z ,也就是 35 35 35 ,我们即可取进制数最大 36 36 36 。所以我们取上边界的公式为 r = m a x ( t a r g e t , 36 l l ) r = max(target, 36ll) r=max(target,36ll) 。而下边界的 l l l 则取 n 2 n2 n2 每一位中的最大值加 1 1 1
  3. 进行二分查找,如果当前进制下的 n 2 n2 n2 的十进制要大于等于 n 1 n1 n1 的十进制 t a r g e t target target ,则令 r = m i d r=mid r=mid ;反之,令 l = m i d + 1 l=mid+1 l=mid+1
  4. 输出最终结果。
代码
#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

//将字符转换成数字
int get(char c)
{
    if (c <= '9')  return c - '0';
    return c - 'a' + 10;
}

//获得十进制值
LL calc(string n, LL r)
{
    LL res = 0;
    for (auto c : n)
    {
        //double存的数字比long long更大
        //如果已经大于1e16则一定大于target,直接返回一个超大值即可
        if ((double)res * r + get(c) > 1e16) return 1e18;
        res = res * r + get(c);	//秦九韶算法
    }
    return res;
}

int main()
{
    string n1, n2;
    cin >> n1 >> n2;
    int tag, radix;
    cin >> tag >> radix;

    if (tag == 2)  swap(n1, n2);    //统一化处理
    LL target = calc(n1, radix);    //获得n1的十进制

    //获得二分的上边界和下边界
    LL l = 0, r = max(target, 36ll);
    for (auto c : n2)  l = max(l, (LL)get(c) + 1);

    //二分查找
    while (l < r)
    {
        LL mid = l + r >> 1;
        if (calc(n2, mid) >= target) r = mid;
        else    l = mid + 1;
    }

    if (calc(n2, r) == target) cout << r << endl;
    else puts("Impossible");

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值