PAT 1010 Radix

过了一天感觉没干什么,想刷一发题弥补一下,正在考虑去做哪道,室友说去试试PAT 1010,果然当年自己直接跳过了这题,一看这通过率(0.07)有点夸张了。题目是已知一个数,求另外一个数的基数,使得这两个数数值上相等。很自然的考虑到使用二分搜索来确定这个基数,数字表示使用[0-9a-z],这tmd的让人很容易的想到基数的范围就在1~36之间了,艹,基数是可以超过这个范围的,如果没有考虑到这一点,可以得到的一个典型分值就是19分。不过基数在[1, 36]之间的话这个搜索范围太小了,直接暴力遍历也可以,于是闷声不响的扩大范围,总之是坑题,哎没办法,老女人就是爱这样。下面给出代码:

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>



using namespace std;



char char2num[128];



int remove_leading_zero(char* str) {

    if (str[0] == '\0') return 0;

    int ri = 0, wi = 0;

    while (str[ri] == '0' || str[ri] == '+' || str[ri] == '-') ri++;

    int len = 0;

    while ((str[wi++] = str[ri++]) != '\0') len++;

    if (len == 0) {

        str[0] == '0';

        str[++len] = '\0';

    }

    return len;

}



long long value(const char* str, int len, long long radix) {

    long long ret = 0;

    long long r = 1;

    for (int i=len - 1; i>=0; i--) {

        int digit = char2num[str[i]];

        // we should check the number validation

        if (digit >= radix) return -1;

        ret += r * digit;

        r *= radix;

    }

    return ret;

}



int inc_cmp(char* str, int len, long long radix, long long target){

    long long v = 0;

    long long r = 1;



    for (int i=len - 1; i>=0; i--) {

        int digit = char2num[str[i]];

        v += r * digit;

        r *=radix;

        if (v > target) {

            return 1;

        }

    }

    if (v == target) {

        return 0;

    } else {

        return -1;

    }

}



long long binary_search(char* str, int len, long long lo, long long hi, long long target){

    long long mid;

    lo = lo - 1;

    hi = hi + 1;



    while(lo + 1< hi){

        mid = (lo + hi) / 2;

        int res = inc_cmp(str, len, mid, target);

        if(res > 0) {

            hi = mid;

        } else if(res < 0) {

            lo = mid;

        } else {

            return mid;

        }

    }

    return -1;

}



int main() {

    // init char2num lookup table

    for (int i=0; i<10; i++) char2num['0' + i] = i;

    for (int i='a'; i<='z'; i++) char2num[i] = i - 'a' + 10;



    char num1[16] = {'\0'};

    char num2[16] = {'\0'};

    char *pnum1 = num1, *pnum2 = num2;

    int tag = 0;

    long long bradix = 0;



    scanf("%s%s%d%ld", num1, num2, &tag, &bradix);



    // we always assure that bradix is the radix of pnum1

    // and pnum2 is which we should guess its radix

    if (tag != 1) {

        pnum1 = num2;

        pnum2 = num1;

    }

    

    int n1len = remove_leading_zero(pnum1);

    int n2len = remove_leading_zero(pnum2);

    

    long long n1 = value(pnum1, n1len, bradix);

    

    bool is_same = !strcmp(pnum1, pnum2);



    if(is_same) {

        if (n1len > 1) {

            // must be same radix, if digits more than one

            printf("%d\n", bradix);

        } else {

            // only one digit, so choose a smallest valid radix

            printf("%d\n", n1 + 1);

        }

        return 0;

    } 



    long long lo = 0;

    for (int i=0; i<n2len; i++) {

        int d = char2num[pnum2[i]];

        if (d + 1> lo) lo = d + 1;

    }



    long long hi = n1 > lo ? n1 : lo;

    int res = binary_search(pnum2, n2len, lo, hi, n1);

    if (res < 0) {

        printf("Impossible\n");

    } else {

        printf("%d", res);

    }



    return 0;

}

 

你可能感兴趣的:(pat)