这题真的是一道神题呀,通过率0.08
1.题目
原题不再重复,大意是:
输入四个数:N1,N2,tag,radix,如果tag为1,则表明N1是radix进制,反之亦然,N1,N2最多为10位数,且每一位都为09或者az,表示0~35
求是否有一个进制使得在此进制下,未知进制的数和另一个数在十进制下相等。存在则输出满足条件最小的进制,不存在则Impossible
2.思路
- 步骤1:将已确定进制的数放在N1,未知的为N2,这样可以方便计算
- 步骤2:将N1转换为10进制
-步骤3:二分法找出N2的最小进制(minRadix):将N2由mid进制转为十进制,如果N2>N1,说明当前进制过大,则,high = mid -1,即往左边继续二分;如果N2<N1,说明当前进制过小,则low = mid +1,即往右边继续二分;如果N2==N1,则说明该进制符合要求,但为求最小(题目要求),因此,更新minRadix的值,继续往左,high = mid -1。二分结束时就可判断解是否存在,存在则获得最小的合适进制(midRadix)。
3.注意点
1.暴力枚举会超时
2.minRadix并不会因为每一位只能表示0~35而使得最大36进制,可能超大哦,所以,要把minRadix和存储十进制下的N1,N2的两个变量(num1,num2)都设置成long long 型
3.当minRadix超大时,要小心计算num2时溢出的问题(num2在转换过程中的某一步小于0了),测试点10专门设了这个坑
4.剪枝的方法:在转换N2的累加过程中,不断去判断结果是否大于N1或者结果是否溢出,如果是,则不必再往下计算了,N2在该进制下一定大于N2
5.N2的进制的范围是:最小比N2中的最大一位数字大1;最大不超过N1的值和N2最小进制中大的那个数
4.代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char n[2][11];
int getbiggist(char n[], int lens)//得到N2中最大的一位数字
{
int biggest = -1;
int temp = 0;
for (int i = 0; i < lens; i++)
{
if (n[i] <= '9'&&n[i] >= '0')
{
temp = n[i] - '0';
}
else
{
temp = n[i] - 'a' + 10;
}
if (temp > biggest)
{
biggest = temp;
}
}
return biggest;
}
int main()
{
int tag;
int radix;
long long num[2] = { 0 };
scanf("%s", n[0]);
scanf("%s", n[1]);
scanf("%d%d", &tag, &radix);
if (tag == 2)
swap(n[0], n[1]);
for (int i = 0; i < strlen(n[0]); i++)//把N1转为10进制存起来
{
if (n[0][i] <= '9'&&n[0][i] >= '0')
{
num[0] = num[0] * radix + (n[0][i] - '0');
}
else
{
num[0] = num[0] * radix + (n[0][i] - 'a' + 10);
}
}
long long low= getbiggist(n[1], strlen(n[1])) + 1;
long long high = max(num[0] + 1, (long long)low);
long long minRadix = high + 1;
long mid = 0;
int i = 0;
while (high >= low)
{
mid = (high + low) / 2;
num[1] = 0;
for (i = 0; i < strlen(n[1]) && num[1]<num[0] && num[1] >= 0; i++)
{
if (n[1][i] <= '9'&&n[1][i] >= '0')
{
num[1] = num[1] * mid + (n[1][i] - '0');
}
else
{
num[1] = num[1] * mid + (n[1][i] - 'a' + 10);
}
}
if (i == strlen(n[1]) && num[1] == num[0])
{
minRadix = mid;//更新minRadix的值
high = mid - 1;
}
else
{
if (num[1] >= num[0] || num[1] <= 0)
high = mid - 1;
else
low = mid + 1;
}
}
if (minRadix != max(num[0] + 1, (long long)smallest) + 1)
printf("%lld", minRadix );
else
printf("Impossible\n");
return 0;
}
一件无聊的小事
无聊玩了一下,测试点14,17,18,19,2的答案是impossible,测试点3,4,5的答案是38,测试点10要考虑N2转换过程中溢出问题。。。。唔,那就是说我直接输出printf("Impossible\n");也可以拿个7分, (-_-!!)