1010. Radix

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

题意

给定两个不同(也可能相同)进制下的数字,其中一个数字的进制已知,要求判断另一个数在某个进制下是否与已知数相等。

思路

这是我目前为止碰到的比较莓良心的题,有很多坑:

  1. 最大进制数并不是想当然的36,而是最大可以到达long long级别的。因为对于36以上的进制,数中每一位都可以使用不大于35的数字。例如, 1 0 ( 1000 ) = 1000 10_{(1000)} = 1000 10(1000)=1000,但它并没有使用超过’z’的字符。
  2. 待求进制的上下限需要自己确定。下限比较容易求,根据题目给出的信息,下限是待求数中最大数字+1。上限是已知数十进制转换后得到的数x加1,原因如下:
    1. 若待求数y至少有两位,说明 y ≥ r a d i x y \geq radix yradix(最小为10), 所以必须满足 r a d i x ≤ x radix \leq x radixx,否则x与y不可能相等;
    2. 若y只有一位(y在任何大于y的进制下的数就是y本身),则理论上只要x与y相等,y的进制可以是任意大于y的数(不然不可能只有一位),没有上限,但受到要输出最小进制的限制,上限就必须是 x + 1 (x == y 是前提)。
  3. radix的范围较大,直接顺序遍历会超时,必须使用二分查找;
  4. 由于radix可能很大,所有变量都应该设置成long long;
  5. radix很大时,十进制转换得到的数可能超过long long上限而变负数,必须把这种情况也考虑在内。

代码实现

#include <iostream>
#include <string>
using namespace std;

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

long long toDecimal(string s, long long radix)      // 转换成十进制数
{
    long long sum = 0;

    for (int i = 0; i < s.length(); i++)
        sum = sum * radix + toNum(s[i]);

    return sum;
}

long long findMax(string s)         // 找到待求数中的最大数字
{
    long long maxD = -1;

    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] <= '9' && s[i] >= '0' && s[i] - '0' > maxD)
            maxD = s[i] - '0';
        else if (s[i] <= 'z' && s[i] >= 'a' && s[i] - 'a' + 10 >maxD)
            maxD = s[i] - 'a' + 10;
    }

    return maxD;
}

long long binarySearch(long long left, long long right, string s, long long x)      // 二分查找
{
    while (left <= right)
    {
        long long mid = (left + right) / 2;
        long long y = toDecimal(s, mid);
        if (y < 0 || y > x)         // 转换得到的数超过long long上限而变负的情况,应该归属到偏大分支中
            right = mid - 1;
        else if (y < x)
            left = mid + 1;
        else
            return mid;
    }

    return -1;          // 不存在满足的radix
}

int main()
{
    string a, b;
    int tag;
    long long radix, x;
    long long ans;

    cin >> a >> b >> tag >> radix;

    x = toDecimal(tag == 1? a : b, radix);
    string s = (tag == 1? b : a);

    ans = binarySearch(findMax(s) + 1, x + 1, s, x);        // 下限、上限确定

    if (ans == -1)
        cout << "Impossible";
    else
        cout << ans;

    return 0;
}

参考

CSDN博客 - xuxumoi

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值