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就看答案。时间有限。