PAT_1010. Radix

来源:互联网 发布:mac新系统不能用word 编辑:程序博客网 时间:2024/06/08 17:18

////  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