PAT_1010. Radix

//
//  main.cpp
//  PAT_1010. Radix
//
//  Created by wjq on 17/3/30.
//  Copyright © 2017年 wjq. All rights reserved.
//
// N1 N2 tag radix
#include <iostream>
#include <string.h>
#define MIN(a,b) (a)<(b)?(a):(b)
using namespacestd;
int tag;
char N1[15],N2[15],sourceN[15],targetN[15];
long longint radix,sourceNum,low,high,mid;
long longint CharToDecimal(char N[],longlong int jinzhi)
{
    longlong int sum=0,n=1;
    for(int i=(int)strlen(N)-1;i>=0;i--)
    {
        if(isdigit(N[i]))
            sum+=(N[i]-'0')*n;
        elseif(isalpha(N[i]))
            sum+=(N[i]-'a'+10)*n;
        n*=jinzhi;
        if(sum<0)
            return -1;
    }
    return sum;
}
long longint BinarySearch()
{
    low=2;
    for(int j=0;j<strlen(targetN);j++)
    {
        longlong int temp=0;
        if(isdigit(targetN[j]))
            temp=targetN[j]-'0';
        else
            temp=targetN[j]-'a'+10;
        if(temp>low)
            low=temp+1;
    }
    high=sourceNum+1;
    while(low<=high)
    {
        mid=(low+high)/2;
        if(CharToDecimal(targetN,mid)==sourceNum)
            returnmid;
        elseif(CharToDecimal(targetN,mid)<sourceNum&&CharToDecimal(targetN,mid)!=-1)  
            low=mid+1;
        else
            high=mid-1;
    }
    return -1;
}
void Sure()
{
    if(tag==1)
    {
        strcpy(sourceN,N1);
        strcpy(targetN,N2);
        sourceNum=CharToDecimal(N1,radix);
    }
    else
    {
        strcpy(sourceN,N2);
        strcpy(targetN,N1);
        sourceNum=CharToDecimal(N2,radix);
    }
    
}
int main(int argc,const char * argv[])
{
    cin>>N1>>N2>>tag>>radix;
    if(strcmp(N1,"1")==0&&strcmp(N2,"1")==0)
        cout<<2;
    elseif(strcmp(N1,N2)==0)
    {
        if(strlen(N1)==1)
        {
            if(tag==1)
            {
                if(isalpha(N1[0]))
                    cout<<(MIN(radix,N2[0]-'a'+11));
                elsecout<<(MIN(radix,N2[0]-'0'+1));
            }
            else
            {
                if(isalpha(N1[0]))
                    cout<<(MIN(radix,N2[0]-'a'+11));
                elsecout<<(MIN(radix,N2[0]-'0'+1));
            }
        }
        elsecout<<radix;
    }
    else
    {
        Sure();
        if(BinarySearch()==-1)
            cout<<"Impossible";
        else
            cout<<BinarySearch();
    }
}



思路:

根据tag确定源字符和目标字符,通过源进制算出源数,再通过枚举目标进制算出目标数,若目标数与源数相同,就输出目标进制.


这题的坑点太多了,开始的时候没有用二分,直接从2开始循环来做,有三个点过不去,查了资料之后.

重新写了一遍代码.


1.用二分法是如何保证找出来的进制是最小的?

明确一点,如果为目标字符是二位以上的,那么不同进制转换出来的目标数一定不相同,且目标数随进制的增大而增大.

如果目标字符只有一位,那就要注意了,转换的时候targetNum=targetN[0]*jinzhi^0=target[0],你会发现目标数不随进制的增大而改变.

举个例子,3 3 1 10,tag=1表示第一个3是10进制的,求第二个3的进制,显而易见,第二个3的进制可以是4,5,6,7,8,9,10,11......

因此必须在二分之前解决这种情况

当然这个例子比较特殊,如果源字符和目标字符不相同,比如 3 5 1 10,那你会发现,无论是几进制,这两个数都不会相同.原理还是这条公式targetNum=targetN[0]*jinzhi^0=target[0].


因此讨论清楚了,区分目标字符数是一位或者二位的来解决.


2.为什么要用long long int ?

题意中说明了 源数中出现的最大字符是z,也就是35,源数最大的位数是10.虽然没有说radix的范围,我们就假设radix只有35

那么我们做个估计,假设源字符是zzzzzzzzzz,大概是 35*35^9=35^10<40^10=4^10*10^10 可以估计源数肯定超过10个0,int是存不下的.

并且,zzzzzzzzzz 10 1 35 在这个例子中,目标数等于目标进制等于源数的大小.因此目标进制和目标数也必须声明为long long int.


3.二分法的上界下界 ?

上界只要比源数大1,那么一定能够满足了.

下界要比目标字符中的任何一位上的数大1.

假设目标字符是 ab1 他不可能是2进制的,因为2进制只有两个数01.因此ab1至少是12进制的.


4.这一点我尚存疑惑.因为不知道超出long long int范围之后sum的值究竟是如何变化的,我不确定返回的sum一定是个负数.

在枚举目标进制计算目标数的时候,目标数的大小有可能超出long long int的范围,这时候返回的sum可能是一个负数,如果你不加判断,那么会导致你返回的值一直比源数小,程序会让low=mid+1,然后继续计算,导致目标数越来越大,我们知道,源数一定是在long long int范围内的,既然目标数在目标进制下已经超出long long int范围了,应该要让high=mid-1来缩小目标数来接近源数才对.


5.边界条件

1 1 2 2 或者1 1 1 2 这种例子,必须输出2.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值