PAT-A-1010 Radix (25 分) 二分求解

53 篇文章 0 订阅
30 篇文章 1 订阅

1010 Radix (25 分)

题目传送门:PAT-A-1010 Radix (25 分)

一、题目大意

给出两个数n1,n2,还给出tag和radix,如果tag为1,则radix为n1的进制,如果tag=2,则radix为n2的进制,求另一个数在什么进制下与这个数相等。

二、解题思路

首先:当tag=2时,swap(n1,n2)

此题有坑。我刚开始以为所求进制只是从2到36,因为输入的两个数中只有0-z,分别代表基数0-35,然鹅,提交了好多次,总是有四组数据过不了???,最后我发现题目并没有明确说明所求进制是36以内的。按理说进制就可能无限大,那么我们要怎么求出最小可能的进制呢。

我们可以分析一下,题目说了n1和n2长度不超过10,那么最大的数就是10个z,而10个z这种数至少是36进制,因为每一位数字不能超过其进制的基数。

36^10=3656158440062976,这个数已经超过了32int范围,但没有超过64位整数long long范围,我们可以是用long long 来存储十进制的值。

想要找到最小满足条件的进制,我们可以使用二分查找,二分的最小范围是n2这个数中最大位加1(也就是最小可能的进制数),二分的最大范围是n2这个数最大位加1的值与n1的十进制值的最大值。

然后进行常规二分操作即可。由于我二分写的不好,所以我每次在找到一个解的时候就记录下来,找到更小的就更新它,这样子我觉得会简单一点。当然那些代码写的好的人,直接用left记录最小解,不过我这样写经常会死循环调试半天,索性多花个变量记住解反而省事~

三、AC代码

#include <bits/stdc++.h>
using namespace std;
template<typename T = int>
T read(){
    T x;
    cin >> x;
    return x;
}
typedef unsigned long long ll;
ll getRadix(string s, int radix){
    ll ret = 0;
    for(int i = 0; i < s.size(); i++){
        int t;
        if(s[i] >= 'a'){
            t = s[i] - 'a' + 10;
        }else{
            t = s[i] - '0';
        }
        ret = 1LL*ret * radix + t;
    }
    return ret;
}
int main(){
    freopen("input.txt", "r", stdin);
    string n1 = read<string>(), n2 = read<string>();
    int tag = read(), radix = read();
    if(tag == 2) {
        swap(n1, n2);
    }
    ll x = getRadix(n1, radix);
    ll min_radix = 0;
    for(auto i: n2){
        if(isdigit(i)){
            if(i - '0' > min_radix)
            min_radix = i - '0' + 1;
        }else{
            if(i - 'a' + 10 > min_radix)
            min_radix = i - 'a' + 10 + 1;
        }
    }
    ll left = min_radix, right = max(x, min_radix);
    ll best = 0;
    while(left <= right){
        ll mid = (left + right ) >> 1;
        ll t = getRadix(n2, mid);
        if(t < 0 || t > x){
            right = mid - 1;
        }else{
            left = mid + 1;
            if(t == x){
                best = mid;//更新最优解
            }
        }
    }
    if(best){
        cout << best << endl;
    }else
    cout << "Impossible" << endl;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值