解题的注意问题
这个题目有几个坑:
- 1、数字的范围超过了int的范围,需要用到long long,unsigned int估计也能解决能不能解决;
- 2、有时间的限制,必须用采用二分法来比较,而不能通过从小到大的比较方法;二分法退出有个问题就是:最终radixbeg == radixend -1时,radixmid始终等于radixbeg,此时要特殊处理。
- 3、二分法从两端向中间就要求大端的redix不能太大,太大会超出整型数字的表示范围,此时用开方求得radix的上限。数字范围的计算比较关键
- 4、数字只有一位时,radix对数值没有影响,此时直接比较大小,减少时间开支;而且也只有这种情况下radix可能不唯一,返回radixBeg。
#include<stdio.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
//将字符串转换成记录每个数字记录一位数值的int数组
int getNums(int* nums, char* ch);
//给定进制,将int数组转换成数字
long long getNum_total(int* nums, int len, int radix);
//求给定数字中的最大数值,最小radix = max + 1;
int get_max_num(const int* nums, int len);
int getNums(int* nums, char* ch)
{
int retval = strlen(ch);
int j = 0, i = 0;
while (ch[i] - '0' == 0)
++i;
for (; i < retval; ++i, ++j)
{
if (ch[i] - '0' <= 9)
{
nums[j] = ch[i] - '0';
}
else
nums[j] = ch[i] - 'a' + 10;
}
return (j);
}
long long getNum_total(int* nums, int len, int radix)
{
long long retval = 0;
for (int i = 0; i < len; ++i)
{
retval = retval * radix + nums[i];
}
return retval;
}
int get_max_num(const int* nums, int len)
{
int max = nums[0];
for (int i = 1; i < len; ++i)
{
max = (max > nums[i] ? max : nums[i]);
}
return max;
}
int main()
{
//inf、tag、radix用来记录输入;
char inf[2][11];
//nums是用整数数组来记录输入的数字,len记录对应数字的长度;
int tag = 0, radix = 0, len[2], nums[2][10];
//radixBeg和radixEnd记录二分查找的两端,result代表最终的结果
int radixBeg = 0, radixEnd = 0, result = 0;
//N用来记录转换成十进制时的数字。
long long N[2] = { 0,0 };
//输入数据
scanf("%s %s %d %d", inf[0], inf[1], &tag, &radix);
--tag; //实际输入的数值转换成下标
//因为"0~9"跟"a~z"在编码上不连续,转换成int数组之后后续处理更方便
for (int i = 0; i < 2; ++i)
{
//将字符串转换成int数组来记录
len[i] = getNums(nums[i], inf[i]);
}
//求出给定radix的数字的实际值。
N[tag] = getNum_total(nums[tag], len[tag], radix);
//求出radix检验范围的下限
radixBeg = get_max_num(nums[1 - tag], len[1 - tag]) + 1;
//求出radix检验范围的上限
radixEnd = (int)pow((double)(N[tag]/nums[1-tag][0]),(double)(1.0/(double)(len[1-tag]-1)));
//如果不是一位数字二分查找的方法来校验radix
if (len[1 - tag] != 1)
{
int radixMid = radixBeg + (radixEnd - radixBeg) / 2;
do
{
N[1 - tag] = getNum_total(nums[1 - tag], len[1 - tag], radixMid);
if (N[1 - tag] == N[tag])
{
result = radixMid;
break;
}
else if (N[1 - tag] > N[tag])
{
radixEnd = radixMid;
radixMid = radixBeg + (radixEnd - radixBeg) / 2;
}
else
{
/*加了这个判断语句是为了解决当二分查找进行到radixEnd == radixBeg + 1时,
如果没有这段代码,将退不出循环*/
if (radixEnd == radixBeg + 1)
{
N[1 - tag] = getNum_total(nums[1 - tag], len[1 - tag], radixEnd);
if (N[1 - tag] == N[tag])
{
result = radixEnd;
}
break;
}
radixBeg = radixMid;
radixMid = radixBeg + (radixEnd - radixBeg) / 2;
}
} while (radixEnd > radixBeg);
}
else
{ //当只有一位数字时,直接求值
N[1 - tag] = nums[1 - tag][0];
if (N[1 - tag] == N[tag])
result = radixBeg;
}
//得到result则输出result;否则,输出Impossible
if (result)
printf("%d", result);
else
printf("Impossible");
getchar();
getchar();
return 0;
}