pat1010-穷举vs二分查找

本文探讨了如何解决两个正整数在不同进制下相等的问题,通过使用二分查找算法来寻找合适的进制,避免了遍历方法的效率低下,并解决了大进制下数值溢出的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1010. Radix

Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is "yes", if 6 is a decimal number and 110 is a binary number.

Now for any pair of positive integers N1 and N2, your task is to find the radix of one number while that of the other is given.

Input Specification:

Each input file contains one test case. Each case occupies a line which contains 4 positive integers:
N1 N2 tag radix
Here N1 and N2 each has no more than 10 digits. A digit is less than its radix and is chosen from the set {0-9, a-z} where 0-9 represent the decimal numbers 0-9, and a-z represent the decimal numbers 10-35. The last number "radix" is the radix of N1 if "tag" is 1, or of N2 if "tag" is 2.

Output Specification:

For each test case, print in one line the radix of the other number so that the equation N1 = N2 is true. If the equation is impossible, print "Impossible". If the solution is not unique, output the smallest possible radix.

Sample Input 1:
6 110 1 10
Sample Output 1:
2
Sample Input 2:
1 ab 1 2
Sample Output 2:
Impossible


解释说明:

为了方便起见,假定tag=1。 radix 表示的一个数的进制,tempRadix表示第二个数的进制,number表示第一个数在进制radix下的值,tempNum表示第二个数在tempRadix进制下的值。

策略一、用穷举法,计算另一个数的进制,进制值从2开始递增,一旦发现该进制过大,则输出Impossible

              该办法仅适用数比较小的情况,当number较大时,会超时。测试用例7会超时。

策略二、用二分法,

               最小可能进制minRadix为另一个数中最大的字符对应的数加一(ab 对应 12,96 对应 10),

               最大可能进制maxRadix=(number+1)>(minRadix+1)?(number+1):(minRadix+1)

               该方法由于可能出现非常大的进制,因此计算该进制下第二个数的值时会产生溢出(就算用了long long类型还是会的,100^10 > 2^64 .....) ,进而导致第二个数的值为负值,二分的逻辑就认为进制还不够大,然后就悲剧了。。。。


试试下面两个测试用例吧:

10000 10 1 28          --->  614656


10000 96100 1 28   --->  16

解决方案:

还是用二分法吧,当出现溢出时,特殊处理一下就好了。

将字符串转换为数值的函数如下:

long long strToNumber(char str[MAX_N],long long radix){
    int len=strlen(str);
    long long number = 0;
    long long weight = 1;

    for(int i=len-1;i>=0;i--){
        number += weight*charToNum[str[i]];

        if((number < 0) || (weight*charToNum[str[i]] < 0)){//如果溢出了返回-1
            return -1;
        }

        weight *= radix;

        if((weight < 0) && (i > 0)){//如果溢出了返回-1
            return -1;
        }
    }

    return number;
}

 二分查找部分特殊处理:

    //改用二分查找
    long long tempRadix;
    long long tempNum;
    bool noWay = true;

    long long maxRadix,minRadix;
    minRadix = findMinRadix(n2);
    maxRadix = (number+1)>(minRadix+1)?(number+1):(minRadix+1);
    tempRadix = minRadix;
    while(minRadix <= maxRadix){
        tempNum = strToNumber(n2,tempRadix);

        if(tempNum == -1){//发现溢出时,进制过大了!
            maxRadix = tempRadix - 1;
        }
else{
            if(tempNum > number){
                maxRadix = tempRadix-1;
            }else if(tempNum < number){
                minRadix = tempRadix+1;
            }else{
                noWay = false;
                break;
            }
        }

        tempRadix = (minRadix+maxRadix)/2;
    }


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值