PAT 甲级 1010 Radix (25 分)(Java)
题目
题意解读
这题的大体意思就是给两个数N1和N2,数位长度不超过10,并指出其中一个数是几进制数,然后问另一个数用多少进制表示,可以使得N1==N2;
解题思路
首先要明确的一个点是:
虽然题目表明了其中给出进制的数一定会是35进制以内的数,假设为N1,因为使用0-9,a-z只能表示到最高35进制,但这并不意味着另一个数也是如此,另一个数的进制最大应该是多少呢?应该是N1十进制表示的数,如10000 10 1 10 这个输入,表明10000是10进制数,此时第二个数若是10000进制数,此时两者是相等的;那是否会有这样的疑问?哪有这么多字母表示10000进制数的每个数位,这我们不需要担心,因为压根不用我们考虑,因为我们无需表示出来,只需要知道这是多少进制数即可。
具体的步骤为:
- 首先将N1转化为10进制数;
- 判定出N2的最小进制和最大进制,最小进制就是自身数位最大值加1,最大进制就是N1的十进制数和N2最小进制的较大值,这里之所以取较大值,是判定特殊情况的,如果有疑问可以想想6 6 1 10这个输入,题目的第0个测试用例;
- 最后就是通过二分法进行进制的查找,这里的转换为10进制的过程中可能出现溢出,需要进行判断;
解法
解法一
import java.util.Scanner;
public class Main {
/**
* 将字符串中的数字以radix进制转换为10进制的数字
* @param s
* @param radix
* @return 转换后的十进制数
*/
public static long toTen(String s, long radix){
long res = 0;
long exp = 1;
char[] ch = s.toCharArray();
for(int i = ch.length-1; i >= 0; --i){
char c = ch[i];
int num = 0;
if(c >= '0' && c <= '9'){
num = c - '0';
}else if(c >= 'a' && c <= 'z'){
num = c - 'a' + 10;
}
res += num * exp;
exp *= radix;
if(res < 0 || exp < 0){
return -1;
}
}
return res;
}
// 得出当前数字所有数位的最大值
public static long getMax(String another){
long max = -1;
for(int i=0; i<another.length(); ++i){
char c = another.charAt(i);
int num = 0;
if(c >= '0' && c <= '9'){
num = c - '0';
}else if(c >= 'a' && c <= 'z'){
num = c - 'a' + 10;
}
max = Math.max(num, max);
}
return max;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] st = sc.nextLine().split(" ");
String n = st[0];
String m = st[1];
int tag = Integer.valueOf(st[2]);
int radix = Integer.valueOf(st[3]);
long origin;
String another;
if(tag == 1){
origin = toTen(n, radix);
another = m;
}else{
origin = toTen(m, radix);
another = n;
}
long max = getMax(another);
long i = max + 1, j = Math.max(origin, i);
while(i <= j){
long mid = (i + j) >> 1;
long ano = toTen(another, mid);
if(ano == origin) {
System.out.println(mid);
return;
}else if(ano == -1 || ano > origin){
j = mid - 1;
}else{
i = mid + 1;
}
}
System.out.println("Impossible");
}
}