题意:
给定两个数和其中一个数的基数,求取使两个数相等的最小基数,保证数字中的数肯定小于基数;
分析:
1、首先计算出给定基数的那个数的十进制形式;
package AdvancedLevelPractice;
import java.util.Scanner;
public class pat1010 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
String N1 = scanner.next();
String N2 = scanner.next();
long tag = scanner.nextInt();
long radix = scanner.nextInt();
String tmpString;
if(tag == 2){
tmpString = N1;
N1 = N2;
N2 = tmpString;
}
long N1Decimal = getDecimal(N1,radix);
long low = getLow(N2);
long high = N1Decimal;
long radix2 = -1;
if(low >= high){
radix2 = compare(N1Decimal, N2, low);
}else {
radix2 = getResults(radix2, N1Decimal, N2, low, high);
}
if(radix2 == -1){
System.out.print("Impossible");
}
else {
System.out.print(radix2);
}
scanner.close();
}
private static long compare(long n1Decimal, String n2, long radix) {
// TODO Auto-generated method stub
while(true){
long sum = 0;
long h = 1;
for(int i = n2.length() - 1; i >= 0; i--){
char ch = n2.charAt(i);
if(ch <= '9'){
sum += (ch - '0') * h;
}
else {
sum += (ch - 'a' + 10) * h;
}
h *= radix;
if(sum > n1Decimal){
return -1;
}
}
if(sum == n1Decimal){
return radix;
}
radix++;
}
}
private static long getResults(long radix2, long n1Decimal, String n2, long low, long high) {
// TODO Auto-generated method stub
long radix = (low + high) / 2;
//System.out.println(low+"\t"+high+"\t"+"radix = "+radix);
long sum = 0;
long h = 1;
for(int i = n2.length() - 1; i >= 0; i--){
char ch = n2.charAt(i);
if(ch <= '9'){
sum += (ch - '0') * h;
}
else {
sum += (ch - 'a' + 10) * h;
}
if(sum > n1Decimal || sum < 0){
high = radix - 1;
return getResults(radix2, n1Decimal, n2, low, high);
}
h *= radix;
}
if(sum == n1Decimal){
radix2 = radix;
high = radix - 1;
return getResults(radix2, n1Decimal, n2, low, high);
}
if(low >= high){
return radix2;
}
if (sum < n1Decimal) {
low = radix + 1;
return getResults(radix2, n1Decimal, n2, low, high);
}
return radix2;
}
private static long getLow(String n2) {
// TODO Auto-generated method stub
long radix = 0;
long tmp;
for(int i = n2.length() - 1; i >= 0; i--){
char ch = n2.charAt(i);
if(ch <= '9'){
tmp = ch - '0';
}
else {
tmp = ch - 'a' + 10;
}
if(tmp > radix){
radix = tmp;
}
}
radix++;
return radix;
}
private static long getDecimal(String n1, long radix) {
// TODO Auto-generated method stub
long sum = 0;
long h = 1;
for(int i = n1.length() - 1; i >= 0; i--){
char ch = n1.charAt(i);
if(ch <= '9'){
sum += (ch - '0') * h;
}
else {
sum += (ch - 'a' + 10) * h;
}
h *= radix;
}
return sum;
}
}
2、求得另一个数的最大数位,然后基数从该位值加1开始,如果最小基数大于第一个数,则已经可以确定Impossible;
3、避免超时,用二分查找法查找该基数:如果在计算过程中,该数已经大于大于第一个数了,那么在左半边中查找基数;如果计算完毕,此数还是小于第一个数,那么在右半边中查找基数;如果计算完毕,两个数相等了,那么记录该值,并从左半边继续查找更小的基数;如果基数为最小基数或者最大基数时,两个数还是不相等,那么结束递归。
4、注意所有变量设置为long型,当实例为zzzzzzzzzz zzzzzzzzzz 1 36时,基数太大的话,计算出的和会超出long所能表达出的最大值,然后变为负值,要特别注意!!