PAT(Advanced Level) 1010 Radix

1. 10个数位且进制不定->用int可能溢出,应该用long long存储。

    printf("%d\n", __INT_MAX__);
    printf("%d\n", (1<<31)+1);
    printf("%d\n", __INT_MAX__+1);
    printf("%lld\n", __LONG_LONG_MAX__);
    printf("%lld\n", __LONG_LONG_MAX__+1);
    printf("%lld\n", (1LL<<63)+1);

2147483647
-2147483647
-2147483648
9223372036854775807
-9223372036854775808
-9223372036854775807

所以超过10的九次方的数要用long long存储。 

2.二分搜索上下界的确定

下界:应当比出现的最大数大1。

上界:考虑极端情况。

3.技巧:哈希思想,先打表,之后只要查表就可以,不用每次都算了。int Map[256],字符类型直接就可以做数组下标。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctype.h>
#include <algorithm>
using namespace std;

typedef long long LL;
LL inf = (1LL<<63) - 1;

int Map[256] = {0};
void Init(){
    for (char ch='0'; ch<='9'; ch++) {
        Map[ch] = ch - '0';
    }
    for (char ch='a'; ch<='z'; ch++) {
        Map[ch] = ch - 'a' + 10;
    }
}

LL toDecimal(LL originalRadix, char *num, LL ub){
    LL decimal = 0;
    int len = (int)strlen(num);
    for (int i=0; i<len; i++) {
        decimal = decimal * originalRadix + Map[num[i]];
        if (decimal<0 || decimal>ub) {
            return -1;
        }
    }
    return decimal;
}

int findLowerBound(char *num){
    int lb = 2;
    int len = (int)strlen(num);
    for (int i=0; i<len; i++) {
        if (Map[num[i]]>=lb) {
            lb = Map[num[i]] + 1;
        }
    }
    return lb;
}

int cmp(char *num, LL radix, LL t){
    LL value = toDecimal(radix, num, inf);
    if (value < 0) {
        return 1;
    }
    if (value < t) {
        return -1;
    }
    if (value == t) {
        return 0;
    }
    else{
        return 1;
    }
}

LL BinarySearch(LL d, char *num, LL low, LL high){
    while (low <= high) {
        LL mid = (low + high) / 2;
        int flag = cmp(num, mid, d);
        if (flag == 0) {
            return mid;
        }
        if (flag > 0) {
            high = mid - 1;
        }
        else{
            low = mid + 1;
        }
    }
    return -1;
}

char N1[15], N2[15], temp[15];
int tag, radix;
int main(int argc, const char * argv[]) {
    Init();
    
    scanf("%s %s %d %d", N1, N2, &tag, &radix);
    
    LL result = 0;
    if (strcmp(N1, N2) == 0) {
        result = radix;
    }
    else{
        if (tag == 2) {
            strcpy(temp, N1);
            strcpy(N1, N2);
            strcpy(N2, temp);
        }
        LL value = toDecimal(radix, N1, inf);
        LL low = findLowerBound(N2);
        LL high = max(value, low) + 1;
        result = BinarySearch(value, N2, low, high);
    }
    
    
    
    if (result == -1) {
        printf("Impossible");
    }
    else{
        printf("%lld", result);
    }
    return 0;
}

1.半小时写出第一版只得3分,认真复审代码、重新读题改正一些错误完善考虑问题的全面程度后整到18分,至此两小时。拖延两小时到十一点看源码,上界、溢出的处理不太理解,照着实现一遍才AC。编译原理老师说学习和厨师做菜很像,常常需要炸个半熟捞出来然后过一阵再重新下锅炸。学习是一个螺旋式前进的过程,第一遍看不全懂是正常的,过一段时间再回头看会有新的理解。c++老师说看代码不要死抠末节,要看关键部分,理解核心算法。王小波说真正的学问不在字句而在思想。

所以,有不懂的地方暂丢,之后有机会再取出来看看。自己写的时候当然要注意细节(否则排查错误极其耗时),但看别人代码时重点在于理解并学习核心方法。

2.这题不看解析哪里知道radix竟然不是在[2,36]而是可能达到LL上界,还有溢出的处理、搜索上界的设置不看答案根本想不到。

所以,设置时间限制,在规定时间内没AC就看答案。时间有限。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值