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; }