在连做了几道简单题以后,突然被这么一道难住,心态还是有点崩的,尤其还是怎么调试都调试不出来,终于,收集了各方资料,不断修改算法,总算拿到了AC,喜大普奔~
现在说题目,题目要求找另一个数是否存在在某一个进制的情况下等于指定的数,这道题的陷阱可以总结如下:
- 进制的范围:题目只说了单个数的范围不超过35,但并没有说进制不能超过35;
- 数的大小:单纯的int是不足以拿到这道题的AC的,但好在使用long long int足够了,这里不光是存的数字要用long long int,同时进制也得用long long int。
- 由于使用了long long,进制如果是使用遍历,就会造成极高的时间复杂度,所以基本都采用了二分查找法,最后的结果也表明,这种方法在时间上表现也不错。
- 要求是求出满足条件的最小进制。刚开始做的时候脑子没怎么用,就觉得大不了把所有情况遍历一遍,找出最小的就行,做法就是当遇见正好合适的进制的时候将二分查找法的右值放中间,知道遍历完所有情况。这明显很傻,因为后来突然想到,似乎只有某个数为一位的时候才会有多个进制表示的是同一个数的情况,因此将其单独判断就行。
- 最后一个遇到的问题,是high的初始值问题,当取太大,就会有几个测试点过不去,稍微变一点,又会有不同的通过情况,还挺迷的,最后选定的这个初始值能够让所有测试点通过。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define int64 long long int
int64 c2i(char c) {
int64 temp = (int64)(c - '0');
if (temp>9) {
temp -= 39;
}
return temp;
}
int64 findMinbase(char n[11]){
int64 res = 1;
for(int i=0;i<11;i++){
if(c2i(n[i]) > res)
res = c2i(n[i]);
if(n[i] == '\0')
break;
}
return res+1;
}
int64 switchRadix(char n[11], int64 r) {
int i;
int64 result = 0;
int64 time = 1;
for(i = 0; i<11; i++){
if(n[i] == '\0')
break;
}
for (i -= 1; i >= 0; i--) {
result += c2i(n[i])*time;
time *= r;
}
return result;
}
int main(void) {
char n[2][11];
int choose;
int another;
int64 radix;
int64 ans;
int64 que;
int64 low, high;
scanf("%s %s %d %lld", n[0], n[1], &choose, &radix);
another = choose % 2;
que = switchRadix(n[choose - 1], radix);
low = findMinbase(n[another]);
high = 922337203685477580;
if (strlen(n[another]) == 1) {
if (c2i(n[another][0]) == que)
printf("%lld", low);
else
printf("Impossible");
return 0;
}
while (low <= high) {
int64 mid = (high - low) / 2 + low;
ans = switchRadix(n[another], mid);
if (ans > que || ans<0)
high = mid - 1;
else if (ans < que)
low = mid + 1;
else if (ans == que) {
printf("%lld", mid);
return 0;
}
}
printf("Impossible");
return 0;
}
最后需要鞭策自己的是,连个二分查找都还写不利索,还得继续修炼,嗯