题目链接:http://www.patest.cn/contests/pat-a-practise/1010
这道题主要考察进制转换和二分查找,坑的地方主要在大数溢出上,需要使用long long类型。搞定以后挺爽的,哈哈。
题目大意为,给定数a和数b以及数a的进制,求数b的进制,使数a与数b相等。
策略是采取二分查找法,确定的进制上下界中,查找一个进制,使其满足等式。
进制的下界容易确定,必然为数b中最大符号代表的数加上1。进制的上界为数a和数b最大符号代表的数的最大值加上1。(进制必然小于数a,因为比数a大的话,数b必然比数a大;如果数a小于数b中的最大符号,数a必然比数b小,肯定找不到这一进制。)
此进制有可能很大,所以需要采用long long类型。
比较时,有可能提前确定出两数在当前进制下的大小。
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
typedef long long ll;
int char2int(char c)
{
if (c >= '0' && c <= '9')
{
return c - '0';
}
else if (c >= 'a' && c <= 'z')
{
return c - 'a' + 10;
}
else
{
return -1;
}
}
ll str2ll(char num[], ll radix)
{
ll sum = 0;
for (int i = 0; num[i] != '\0'; i++)
{
sum = sum * radix + char2int(num[i]);
}
return sum;
}
int findSmallestRadix(char num[])
{
int max = 0;
for (int i = 0; num[i] != '\0'; i++)
{
if (max < char2int(num[i]))
{
max = char2int(num[i]);
}
}
return max + 1;
}
int compare(ll n1, char n2[], ll radix)
{
ll sum = 0;
for (int i = 0; n2[i] != '\0'; i++)
{
sum = sum * radix + char2int(n2[i]);
if (sum > n1)
{
return 1;
}
}
if (sum > n1)
{
return 1;
}
else if (sum < n1)
{
return -1;
}
else
{
return 0;
}
}
ll biSearch(ll n1, char n2[])
{
ll l = (ll)findSmallestRadix(n2);
ll r = (n1 > l) ? n1 + 1 : l + 1;
ll m;
while (l < r )
{
m = (l + r) / 2;
if (compare(n1, n2, m) == 1)
{
r = m;
}
else if (compare(n1, n2, m) == -1)
{
l = m;
}
else
{
return m;
}
}
return -1;
}
int main()
{
char n1[11];
char n2[11];
char tag;
ll radix;
scanf("%s %s %c %lld", n1, n2, &tag, &radix);
ll r;
switch (tag)
{
case '1':
r = biSearch(str2ll(n1,radix), n2);
break;
case '2':
r = biSearch(str2ll(n2, radix), n1);
break;
}
if (r == -1)
{
printf("Impossible");
}
else
{
printf("%lld", r);
}
return 0;
}