PAT (Advanced Level) Practice 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

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最小进制中大的那个数

#include<iostream>
#include<math.h>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
/*将radix进制的数转化为十进制的数*/ 
long long int stonum(string s,long long radix)
{
	long long num=0;//用来记录十进制数是多少 
	long long temp=0;// 用来记录位数 
	for(int i=s.length()-1;i>=0;i--)
	{
		if(isalpha(s[i]))
		num+=(s[i]-'a'+10)*pow(radix,temp++);
		else 
		num+=(s[i]-'0')*pow(radix,temp++); 		
	}
	return num;
}
/*二分搜索法*/ 
long long int search(long long l,long long r,long long n1,string s/*可以传递string类型*/)
{
	while(l<=r)//在可行的范围内 
	{
		long long mid=(l+r)/2,sum=0,temp=0;
		sum=stonum(s,mid);//函数调用函数 
		
		if(sum==n1)
		return mid;
		
		//溢出了,能不剪枝吗!当溢出时sum<0,此时比0x7fffffff还大 
		if(sum<0)
		r=mid-1;
		else if(sum<n1) l=mid+1;
		else r=mid-1;	
	}
	
	/*出了可行范围 就GAMEOVER了*/ 
	return -1;	
}

int main()
{
  string s1,s2,s;
  int tag,radix;
  long long int n1=0,n2=0;
  cin>>s1>>s2>>tag>>radix;
  
  s=tag>1?s2:s1;//找出已知系数的数的底数 
  n1=stonum(s,radix);//将已知radix的数转化为10进制 
  s=tag>1?s1:s2;//把s赋上另一个数 
  
  /*下面开始去找所求数中所有位数最大的那位,因为所求radix至少比它大*/ 
  long long int max=-1;
  for(int i=s.length()-1;i>=0;i--)
  {
  	if(isalpha(s[i])&&s[i]-'a'+10>max)
  	max=s[i]-'a'+10;
  	else if(isdigit(s[i])&&s[i]-'0'>max)
  	max=s[i]-'0';
  }
  
  /*找出所求数的radix的下界*/
  long long int l=max+1>2?max+1:2;//radix至少是2
  /*求出所求数的radix的上界*/ 
  long long int r=n1>l?n1:l;  
  
  /*寻找 代求出数 的radix*/
  if(search(l,r,n1,s)==-1)
  cout<<"Impossible";
  else
  cout<<search(l,r,n1,s); 
   
  return 0;
} 
#include <algorithm>
#include <string.h>
#include <cctype>
#include <cmath>
#include <iostream>
using namespace std;

char FindMaxElement(char ch[])
{   /* 寻找字符数组中最大的元素 */
    return *max_element(ch, ch+strlen(ch));
}

int charToint(char c)
{   /* 把字符转为数字 */
    return isdigit(c) ? c - '0' : c - 'a' + 10;
}

long long transfer(char ch[], long long radix)
{   /* 转换成十进制 */
    long long sum = 0;
    for (int i = strlen(ch)-1; i >= 0; i--)
        sum += charToint(ch[i]) * pow(radix, strlen(ch)-1-i);
    return sum;
}

long long check(char ch[], long long num)
{   /* 采用二分法进行寻找 */
    long long low = charToint(FindMaxElement(ch))+1, mid; /* 这里下界是ch中最大的字符数值+1 */
    long long high = num > low ? num : low;
    while (low <= high)
    {
        mid = (low+high) / 2;
        long long aws = transfer(ch, mid);
        if (aws < 0 || aws > num)
            high = mid - 1;
        else if (aws == num)
            return mid;
        else
            low = mid + 1;
    }
    return -1;
}

int main(int argc, char const *argv[])
{
    char N1[11], N2[11];
    int tag;
    long long r, radix;
    cin >> N1 >> N2 >> tag >> radix;
    r = tag == 1 ? check(N2, transfer(N1, radix)) : check(N1, transfer(N2, radix));
    if (r == -1)
        cout << "Impossible";
    else
        cout << r;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mlm5678/article/details/82919622