PAT二分法与穷举题目
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 N1 and N2, 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-zrepresent 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
题意分析:
题目一共给出4个数字,前两个为要比较的数字,第三个为tag,若tag为1,则第四位数字也就是radix为第一位数字的基数,否则,为第二位数字的基数,如案例1:10为6的基数,所以6为十进制。
要求的为第二位数字的进制,使得两个数字得以相同,否则输出”Impossibel”
根据题目,我们可以分析出,要求的基数一定大于这个数字中最大的数字, ”A digit is less than its radix“
,如110,则基数一定大于1,所以我们可以从2开始找。再者,若基数算出的数字超过了已给的数字后,再往下计算只会越算越大,所以,已给的数字是终点的可能之一,如6。
还有一种可能,max>num,此时为Impossible,max==num,此时若只有一位数字就为1,否则为Impossible。
这道题我一开始用了Long,因为题目中指出“Here N1 and N2 each has no more than 10
digits.”。Long的长度是64位,若为十进制,则会溢出。
所以只能选用BigInteger来做。
在BigInteger内部是通过int 数组来表示和处理大数据的,理论上BigInteger可以接收任意长度的数字,基本等于我们机器的极限。
计算基数,我们通过穷举+二分,如果不使用二分法,则时间复杂度过不去。
import java.math.BigInteger;
import java.sql.Time;
import java.util.*;
/**
* Created by Boolean on 2018/8/8.
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] num=new String[2];
num[0] = scanner.next();
num[1] = scanner.next();
int tag = scanner.nextInt();
long radix = scanner.nextInt();
int tag_ = 0;
BigInteger sum = convert(num[tag-1],BigInteger.valueOf(radix));
// System.out.println(sum);
if(tag==1)tag_ = 1;
BigInteger max = BigInteger.ZERO;
//先计算给出的数字
for(int i=0;i<num[tag_].length();i++)
{
char ch = num[tag_].charAt(i);
BigInteger t;
if(Character.isDigit(ch))
{
t = BigInteger.valueOf(Character.getNumericValue(ch));
}
else
{
t= BigInteger.valueOf(((int)ch-87));
}
if(t.compareTo(max)==1)max = t.add(BigInteger.ONE);
}
//System.out.println(sum.toString());
int flag = 0;
BigInteger mid = BigInteger.ZERO;
// System.out.println(high+" "+max_);
BigInteger low = max;
BigInteger high = max.max(sum);//high与num相比较
//二分法,【high,low】
while (low.compareTo(high)==-1||low.compareTo(high)==0)
{
mid = low.add(high).divide(BigInteger.valueOf(2));
BigInteger res = convert(num[tag_],mid);
//System.out.println(res.toString());
if(res.compareTo(sum)==1)
{
high = mid.subtract(BigInteger.ONE);
}else if(res.compareTo(sum)==-1)
{
low = mid.add(BigInteger.ONE);
}
else
{
flag = 1;
break;
}
}
//输出
if(flag==0)
{
System.out.println("Impossible");
}
else
{
System.out.println(mid);
}
}
//用给出的基数与字符串,计算出结果
private static BigInteger convert(String str,BigInteger radix)
{
BigInteger sum = BigInteger.ZERO;
// System.out.println("???");
for(int i=str.length()-1,count=0;i>=0;i--,count++)
{
char ch = str.charAt(i);
if(Character.isDigit(ch))
{
sum = sum.add(radix.pow(count).multiply(BigInteger.valueOf(Character.getNumericValue(ch))));
}
else
{
sum = sum.add(radix.pow(count).multiply(BigInteger.valueOf((ch-'a'+10))));
}
// System.out.println(i);
}
return sum;
}
}