【PAT】1010. Radix

关键:注意这里radix没有范围,可以大到longlong溢出,所以比较两个数可以用剪枝方法判断,即设置一个特定的比较方法当溢出时直接返回,另外查找用二分法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;

long long inf = (1LL<<63)-1;
long long Map[256];
long long change(char* a,long long r){
    int len=strlen(a);
    long long res=0;
    long long d=1;
    while(len--){
        res+=Map[a[len]]*d;
        d*=r;


    }
    return res;
}
long long findLowRadix(char* p){
    long long len = strlen(p);
    long long low = 0;
    long long num;
    for(long long i=len-1;i>=0;i--){
        num=Map[p[i]];
        if(num+1>low)low=num+1;
    }
    return low;
}
int compare(char* p,long long radix ,long long target)
 {
     long long len=strlen(p);
     long long m = 1;
     long long num = 1;
     long long sum = 0;
     for(long long i=len-1;i>=0;i--)
     {
         if(p[i]>='a'&&p[i]<='z')
             num= p[i] - 'a' + 10;
         else if(p[i]>='0'&& p[i]<='9')
             num=p[i] - '0';
         sum+=num*m;
         m*=radix;
         if(sum>target)  //avoid  overflow
             return 1;
     }

     if(sum>target)
         return 1;
     else if(sum<target)
         return -1;
     else
         return 0;

 }
long long  Binary_Search(char *p,long long low,long long high,long long top){
    long long mid=low;
    long long tmp;
    while(low<=high){

        tmp=compare(p,mid,top);
        if(tmp>0){
            high=mid-1;
        }else if(tmp<0){
            low=mid+1;
        }else return mid;
        mid=(low+high)/2;
    }
    return -1;
}
int main()
{
    #ifdef LOCAL
        freopen("data.in","r",stdin);
        freopen("data.out","w",stdout);
    #endif // LOCAL
    for(char c='0';c<='9';c++)
        Map[c]=c-'0';
    for(char c='a';c<='z';c++)
        Map[c]=c-'a'+10;
    char a[14],b[14];
    long long radix,tag,low,high,res,taget;
    cin>>a>>b>>tag>>radix;
    if(1==tag){
        taget=change(a,radix);
        low=findLowRadix(b);
        high=(taget+1>low+1)?taget+1:low+1;
        res=Binary_Search(b,low,high,taget);
        if(res==-1)cout<<"Impossible";
        else cout<<res<<endl;
    }
    if(2==tag){
        taget=change(b,radix);
        low=findLowRadix(a);
        high=(taget+1>low+1)?taget+1:low+1;
        res=Binary_Search(a,low,high,taget);
        if(res==-1)cout<<"Impossible";
        else cout<<res<<endl;
    }
    return 0;
}

简化

#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#define FOR(i, x, y) for(int i = x; i <= y; i++)
#define rFOR(i, x, y) for(int i = x; i >= y; i--)
#define MAXN 610
#define MT(x,i) memset(x,i,sizeof(x))
#define oo 0x3f3f3f3f
using namespace std;
typedef long long ll;

ll inf=(1ll<<63)-1;
ll change(char str[],ll radix)
{
    int len=strlen(str);
    ll ans=0;
    FOR(i,0,len-1)
    {
        if(str[i]<='9'&&str[i]>='0'){
            ans=ans*radix+str[i]-'0';
        }else{
            ans=ans*radix+str[i]-'a'+10;
        }
        if(ans<0||ans>inf)return -1;
    }
    return ans;
}



int main()
{


    #ifdef LOCAL
        freopen("data.in","r",stdin);
    #endif // LOCAL
    ll n1,n2,tag,radix;
    char s1[12],s2[12];
    scanf("%s%s%lld%lld",s1,s2,&tag,&radix);
    if(tag==2){
        char tmp[12];
        strcpy(tmp,s1);
        strcpy(s1,s2);
        strcpy(s2,tmp);
    }
    n1=change(s1,radix);
    int len=strlen(s2);
    int ra=0;
    FOR(i,0,len-1)
    {
        int tmp;
        if(s2[i]<='9'&&s2[i]>='0') tmp=s2[i]-'0';
        else tmp=s2[i]-'a'+10;
        ra=max(ra,tmp);
    }
    ra++;
    ll low=ra;
    ll high=max(n1,low)+1;

    ll mid;

    while(low<=high)
    {
        mid=(low+high)/2;
        n2=change(s2,mid);
        if(n2<n1&&n2!=-1){
            low=mid+1;
        }else if(n2>n1||n2==-1){
            high=mid-1;
        }else{
            printf("%lld",mid);return 0;
        }
    }
    printf("Impossible");

    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值