PAT甲级-1010 Radix

题目

 

题目大意

输入四个数n1, n2, tag, radix,如果tag == 1,那么radix是n1的基数,这里的基数是进制基数的意思;如果tag == 2,radix就是n2的基数。题目要求算出当其中一个没有规定radix的数用哪种进制时,其值和另一个数在数值上相等。输出这个进制,如果没有的话,输出不可能。

思路

要求两个数值相等,就要比较这两个数的大小,要用十进制来进行比较。可以将已经规定radix的那个数(数A)的十进制先算出来,然后和另一个数(数B)比较大小。另一个数要尝试不同的进制,可以用二分法来缩短查找时间。

这里用convert()函数实现n进制转换为十进制,用find_radix()来表示查找过程。我们需要知道,进制越大,这个数所对应的数值也越大。二分法中,将low的值设为B中所有字符的最大值,确保进制的合法性,比如8进制最大的字符是7。将high的值设为low和A中的较大值,例如A为16,B为0a,a在个位数,不管咋整十进制的值都是10,所以high怎么设也无力回天了,如果B为10,将B的进制设为16进制,肯定能够大于等于这个A值;如果A < low,要将high设成low,毕竟high不能小于low。

当mid值等于A值,就表示找到了,直接return;当mid大于A值,说明这个进制太大了,要缩小high,若mid < 0,正整数算着算着变成负数了,肯定是大到溢出了,所以也要缩小high。

知识点

isdigit()在<cctype>头文件中,用于判断是否为数字。

max_element() 和 min_element()在<algorithm>头文件中,用于求区间的最大值/最小值,返回迭代器,加*返回迭代器的值。

代码

#include <iostream>
#include <cctype>
#include <math.h>
#include <algorithm>
using namespace std;

long long convert(string n, long long radix){
    long long sum = 0;
    long long temp = 0;  // 记录位权数
    for (int i = (int)n.size() - 1; i >= 0; i--){
        sum += (isdigit(n[i])) ? (n[i] - '0') * pow(radix, temp) : (n[i] - 'a' + 10) * pow(radix, temp);
        // (n[i] - 'a' + 10)是因为在进制中,字母a开始表示10
        temp++;
    }  // isdigit(),在<cctype>头文件
    return sum;
} //将n进制转换为十进制

long long find_radix(string n, long long num){
    char it = *max_element(n.begin(), n.end());  // 找到n中的最大数,在<algorithm>头文件
    long long low = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;
    long long high = max(num, low);
    while (low <= high){
        long long mid = (low + high) / 2;
        long long t = convert(n, mid);
        if (t > num || t < 0){  // t < 0的这种情况是溢出了
            high = mid - 1;
        }else if (t == num){
            return mid;
        }else{
            low = mid + 1;
        }
    }
    return -1;
}  // 找到合适的基数

int main(){
    string n1, n2;
    long long tag, radix, radix_res;
    cin >> n1 >> n2 >> tag >> radix;
    radix_res = tag == 1 ? find_radix(n2, convert(n1, radix)) : find_radix(n1, convert(n2, radix));
    if (radix_res != -1){
        cout << radix_res << endl;
    }else{
        cout << "Impossible" << endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值