PAT Advanced 1010

此题题意:

给你两个数,确定一个数的进制,然后判断另外一个数能否在合理的进制下表示。

如果采用简单的顺序查找,那么可呢会在测试点7运行超时。如果想要过掉这道题,那么要用上二分查找。

二分查找的难点在于选择哪一个区间作为查找的范围。首先来确定下界,下界一定是另外一个数的数位上最大的那一个数。

为什么呢?

因为在进制表示中,一个数每一位中最大的那个数一定是该进制所代表的数小的,例如2f这个数,f是里面最大的一个数,那

么它的进制中最小都应该是16。

下面来确定上界,

上界为被tag表示的那个数的10进制数。这样充分保证了及时数字很小也能表示成tag所表示的数。

下界max(s[i]),上界为max(s,L)

说点体会:

浙大出题出的 就是好,各种边边角角都考虑到了,我在我的change函数里面只是添加了一个等号,测试点18就过不去,

还有就是数字本身超出long long int的那种处理方式,之前没有考虑到相乘之后超过long long int怎么办,只是想着超过int的情况

,而实际上这道题是可能超过long long的,所以这时就需要对函数进行变化,因为tag所表示的值变成10进制后绝不会超过long long

所以只需要在每一次乘的时候与tag所表示的值进行比较,如果超出了,就代表着此时根本就不需要继续乘下去了,所以值保证不会爆掉

#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
#include<climits>
#include<cstdio>
using namespace std;
#define LL long long
string N1, N2;
LL tag, radix;
LL tagN1, tagN2;
LL temptag;
LL change(int radix, string numm, int flag)
{
	int length = numm.length();
	LL sum = 0;
	LL temp = 1;
	for (int i = length - 1; i >= 0; i--)
	{
		if (numm[i] >= 'a'&&numm[i] <= 'z')
		{
			sum += (numm[i] - 'a' + 10)*temp;
		}
		else
		{
			sum += (numm[i] - '0')*temp;
		}
		temp *= radix;
		//加了一个等号,测试点18就过不去,因为这里的等号不能代表能用此时的radix表示
		if (sum > temptag && flag == 1)
			return sum;
	}
	return sum;
}
LL getmaxnum(string s)
{
	int length = s.length();
	int num;
	int max = 0;
	for (int i = 0; i < length; i++)
	{
		if (s[i] >= 'a'&&s[i] <= 'z')
			num = (s[i] - 'a' + 10);
		else
			num = s[i] - '0';
		if (num>max)
			max = num;
	}
	return max + 1;
}
void solve()//binary search
{
	LL flag = -1;//flag has two condition -1 represent Impossible,others represent equal
	LL number = 0;
	LL L, R;
	LL M;
	
	string tempN;
	if (tag == 1)
	{
		tempN = N2;
		temptag = tagN1;
	}
	else
	{
		tempN = N1;
		temptag = tagN2;
	}

	L = getmaxnum(tempN);
	R = L > temptag ? L : temptag;
	while (L <= R)
	{
		M = (L + R) >> 1;
		number = change(M, tempN, 1);
		if (temptag > number)
		{
			L = M + 1;
		}
		else if (temptag < number)
		{
			R = M - 1;
		}
		else if (temptag == number)
		{
			flag = M;
			break;
		}
	}
	if (flag == -1)
		cout << "Impossible\n";
	else
		cout << flag << endl;
}
void input()
{
	cin >> N1 >> N2 >> tag >> radix;
	if (N1 == "1"&&N2 == "1")
	{
		cout << 2 << endl;
		return;
	}
	if (N1 == N2)
	{
		cout << radix << endl;
		return;
	}
	if (tag == 1)
	{
		tagN1 = change(radix, N1, 0);
	}
	else
	{
		tagN2 = change(radix, N2, 0);
	}
	solve();
}
int main()
{
	input();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值