PAT甲级 1010 Radix (25分)

1010 Radix (25分)

Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is yes, if 6 is a decimal number and 110 is a binary number.

Now for any pair of positive integers N​1​​ and N​2​​, your task is to find the radix of one number while that of the other is given.
Input Specification:

Each input file contains one test case. Each case occupies a line which contains 4 positive integers:

N1 N2 tag radix

Here N1 and N2 each has no more than 10 digits. A digit is less than its radix and is chosen from the set { 0-9, a-z } where 0-9 represent the decimal numbers 0-9, and a-z represent the decimal numbers 10-35. The last number radix is the radix of N1 if tag is 1, or of N2 if tag is 2.
Output Specification:

For each test case, print in one line the radix of the other number so that the equation N1 = N2 is true. If the equation is impossible, print Impossible. If the solution is not unique, output the smallest possible radix.
Sample Input 1:

6 110 1 10

Sample Output 1:

2

Sample Input 2:

1 ab 1 2

Sample Output 2:

Impossible

题意:给定N1和N2两个数字,并且给定tag和radix,如果tag=1,说明N1的进制为radix,那么N2的进制就未知,如果tag=2说明N2的进制为radix,那么N1的进制未知,现在的要求是告诉其中一个数字的进制,求解另外一个数字的进制使得两个数字在同一进制下相等,比如样例6 110 1 10,已经说明6的进制为10,110的进制未知,如果我们让110的进制为2,那么转换成和6同一个进制(10进制)就是6,就是相等,现在要求满足这样的条件输出未知进制的最小进制,如果找不到就输出Impossible。

题解:不知道是我想复杂了。。。。首先题目处理很简单,我们进行统一,让所有数字都转换成10进制数,那么针对已经告诉进制的数字可以先进行转换,另外一个数字再查找就行,那么查找另外一个数字的进制有个要求就是进制必须大于这个数字每个的位,比如1acd,那么进制base必须从d+1也就是13+1=14开始搜索,一开始比较偷懒直接暴力从base一直base++搜索,然后有个数据卡住了,超时了,后来才注意到,进制可能为10的7或者8次方这样大,于是我又转换成二分查找,二分查找就比较有趣了,因为二分的左边l=base这个没问题,那么r应该为多少,设置太小可能没把答案包含,设置太大就会爆long long的范围,所以最麻烦的是r的设置,这是一个动态设置,可以想象,如果未知进制的数字的位数为x,并且未知数的第一位为a[0],那么需要满足
a[0]*pow(r,x-1)<=pow(10,18)
于是我们的r可以确定了,r<=pow(pow(10,18)/a[0],1.0/pow(r,x-1))
(备注pow(a,1.0/n)表示对a开n次方)。
但是还要注意一个问题,就是如果未知进制的数字的位数为1,那么就是1.0/0是错误的,需要特判,可以知道,如果未知进制的数字位数为1,那么无论进制是多少结果都是一样的,结果都为a[0]*pow(base,0)=a[0]。

AC代码如下

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//把所有数字统一转换成10进制数 
ll to_data(vector<ll> x,ll base)
{
	ll ans=0,sum=1;
	for(int i=x.size()-1;i>=0;i--)
	{
		ans+=x[i]*sum;
		sum*=base;
	}
	return ans;
}
//输入的数据为字符串,这里用动态数组表示,主要为方便处理'a'-'z' 
vector<ll>get_data(string x)
{
	vector<ll>q;
	for(int i=0;i<x.length();i++)
	{
		if(x[i]>='0'&&x[i]<='9')
		q.push_back(x[i]-'0');
		else if(x[i]>='a'&&x[i]<='z')
		q.push_back(x[i]-'a'+10);
	}
	return q;
}
int main()
{
	//输入为字符串 
	string a,b;
	int co;
	ll base;
	cin>>a>>b>>co>>base;
	//这里统一认为a的进制已经知道,如果co为2进行交换 
	if(co==2)
	swap(a,b);
	//得到a和b对应的每个位上的数字 
	vector<ll>A=get_data(a);
	vector<ll>B=get_data(b);
	//得到a转换成10进制的数字结果 
	ll ansA=to_data(A,base);
	//找到b的最小的进制baseX 
	ll baseX=0;
	for(int i=0;i<B.size();i++)
	baseX=max(baseX,B[i]);
	//至少比最大位的数字大1 
	baseX++;
	//开始2分 
	ll l=baseX,fin,r;
	//特判 
	if(B.size()==1)
		r=baseX;
	else
		r=pow(1e18/B[0],1.0/(B.size()-1));
	while(l<=r)
	{
		ll mid=(l+r)/2;
		if(to_data(B,mid)>=ansA)
		{
			r=mid-1;
			fin=mid;
		}
		else
		l=mid+1;
	}
	//判断结果 
	if(to_data(B,fin)==ansA)
	{
		cout<<fin<<endl;
		return 0;
	}
	else puts("Impossible");
	return 0;
} 
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页