PAT【甲级】1010

题目链接:PAT【甲级】1010
题目简述:给定形式为N1 N2 tag radix的输入用例,N1和N2是两串数字或字母(a-z,即对应十进制为10-35)组成的“数字串”,tag是标记后面radix(基数)是哪一个数字串的基数,为1就是第一个串。
让找出一个基数,来使得未给出基数和给出基数的数字串相等。如果有多个这样的基数,找到最小的那个。(其实这个条件限制很多余,不可能会出现多个不同的基数使得二者相等,毕竟是单调递增的)

#include<bits/stdc++.h>
using namespace std;

//将每次更新基数后的数字串变成十进制数
long long getResult(string& s, long long radix){
    long long temp = 0;
    for (int i = 0; i < s.size();i++){
        if(s[i] >= '0' && s[i] <= '9')
            temp = temp * radix + (s[i] - '0');
        else
            temp = temp * radix + (s[i] - 'a' + 10);
    }
    return temp;
}

int main(){
    string s1, s2;
    long long num, radix;
    long long dest = 0;//记录目标数
    cin >> s1 >> s2 >> num >> radix;
    if(num == 2)
        swap(s1, s2);
    dest = getResult(s1, radix);
    //找出基数下限
    radix = 0;
    for (int i = 0; i < s2.size();i++){
        if(s2[i] >= '0' && s2[i] <= '9')
            radix = max((long long)s2[i] - '0' + 1, radix);
        else
            radix = max((long long)s2[i] - 'a' + 11, radix);
    }
    //进行二分查找最小的基数
    long long radix_h = dest;
    long long radix_l = radix;
    long long temp;
    while(radix_l < radix_h){
        radix = (radix_l + radix_h) >> 1;
        temp = getResult(s2, radix);
        if(temp < 0 || temp >= dest){
            radix_h = radix;
        }else{
            radix_l = radix + 1;
        }
    }
    if(getResult(s2, radix_l) == dest)
        cout << radix_l;
    else
        cout << "Impossible";
    return 0;
}

最开始我去做这道题目的时候,是直接从基数下限radix,开始累加上去,直到相等退出。很可惜这次拿到24分,第七个测试点超时,后来我就去限制if(radix > 1000000) break;这样发现结果错误,再将上限加几个0发现超时,直到我限制到一定范围,才发现测试点那里执行用时300ms,题目限制400ms。我才意识到原来是基数太大了,累加上去很费时间。
很自然想到二分,但是上限是谁?这里犯蠢了,看了别人的博客才知道是dest,很显然的事情。。。。。
接下来直接二分就可以了,二分的时候也要注意

if(temp < 0 || temp >= dest){
     radix_h = radix;
}else{
     radix_l = radix + 1;
}

这个判断,temp < 0是溢出的情况,太大了,要去处理一下,不然又死循环了。

其实上面代码的后面还可以这样写,因为不可能有多个基数:

while(radix_l <= radix_h){
    radix = (radix_l + radix_h) >> 1;
    temp = getResult(s2, radix);
    if(temp < 0 || temp > dest){
        radix_h = radix - 1;
    }else if(temp < dest){
        radix_l = radix + 1;
    }else{
        break;
    }
}
if(getResult(s2, radix) == dest)
    cout << radix;
else
    cout << "Impossible";

看出不同了么?其实这就是写二分时要注意的一个点,它有不同的写法自然也有不同的作用!!!
具体的道理其实是**左闭右开**还是**左闭右闭**,以此来判断区间边界如何变化,与此对应的还有查询目标位置在哪里的判断。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值