【PAT习题】二分 A1010 Radix

题目

题目描述

题意

输入四个整数N1,N2,tag,radix,第tag个数为已知的radix进制数,求未知进制的那个数是否存在,使得这两个数在十进制下相等。若存在,输出满足条件的最小进制,否则输出Impossible。
N1,N2均不超过10个数位,且每个数位均为0-9或a-z。

思路

  • 因为进制越大则该数字串转换为的十进制结果也越大,即是“单调”的,所以可以二分N2的进制来查找满足条件的进制,二分结束时判断解是否存在。
    • 至于“满足条件的最小进制”,感觉应该就是指N1和N2相等且都只有一位的情况吧(?),比如1 1 1 5此时满足条件的进制不唯一,但由于有上界的限制,所以实际上不存在不唯一的问题

注意

  • 用long long存储转换后的十进制数
  • 题中没有说明radix的范围是[2,36]!!!
    • 最小可能是1,最大可能很大。。。这可太坑了
  • 所以计算过程中要判断是否溢出!! 这里将小于0作为判断标准
    • 十进制转换的时候若溢出则返回结果小于0,所以在二分进制时判断若转换后的N2小于0或大于N1则表示该进制过大,应往左子区间继续查找
  • 注意二分边界!!
    • 下界为N2数位中最大的+1
    • 上界为max(下界,N1的十进制值)
      • 当N2和N1都不是一位数时,N2的进制若超过N1的十进制值,则无论进制多少会大于N1,不能满足条件
      • 特殊情况时二者都是一位数且相等时,则进制取多少都可以,但最小值一定不大于(实际上等于)N1的十进制值+1,因为最后由下界决定,而下界=N2+1=N1+1,所以也可以说“上界为max(下界,N1十进制值+1)”

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
long long radix2ten(char N[], int radix){
    long long ans=0;
    int len=strlen(N);
    for(int i=0; i<len; i++){
        if(N[i]>='0' && N[i]<='9') ans=ans*radix+N[i]-'0';
        else ans=ans*radix+N[i]-'a'+10;
    }
    return ans;
}
int findRadix(char N[], long long left, long long right, long long upbound){
    long long mid,Ntrans;
    while(left<=right){
        mid=(left+right)/2;
        Ntrans=radix2ten(N,mid);
        //小于0时判断为溢出,则一定比Ntag大,说明进制过大,应往左子区间移动
        if(Ntrans<0 || Ntrans>upbound) right=mid-1; 
        else if(Ntrans==upbound) return mid;
        else left=mid+1;
    }
    return -1;
}
int main(){
    char N1[15],N2[15],Ntemp[15];
    long long Ntag;
    int tag,radix,ans;
    scanf("%s %s",N1,N2);
    scanf("%d %d",&tag,&radix);
    //保证N1为已知进制数
    if(tag==2){
        strcpy(Ntemp,N1);
        strcpy(N1,N2);
        strcpy(N2,Ntemp);
    }
    Ntag=radix2ten(N1,radix);
    long long left=0,right;
    int len2=strlen(N2),maxi=0;
    //N2进制下界为最大数位+1
    for(int i=0; i<len2; i++){
        if(N2[maxi]<N2[i]) maxi=i;
    }
    if(N2[maxi]>='0' && N2[maxi]<='9') left=N2[maxi]-'0'+1;
    else left=N2[maxi]-'a'+10+1;
    //上界为下界和N1的十进制值中较大的
    right=max(left,Ntag);
    ans=findRadix(N2,left,right,Ntag);
    if(ans==-1) printf("Impossible");
    else printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值