AcWing 124 数的进制转换

题目描述:

编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。这里有62个不同数位{0-9,A-Z,a-z}。

输入格式

第一行输入一个整数,代表接下来的行数。接下来每一行都包含三个数字,首先是输入进制(十进制表示),然后是输出进制(十进制表示),最后是用输入进制表示的输入数字,数字之间用空格隔开。输入进制和输出进制都在2到62的范围之内。(在十进制下)A = 10,B = 11,…,Z = 35,a = 36,b = 37,…,z = 61 (0-9仍然表示0-9)。

输出格式

对于每一组进制转换,程序的输出都由三行构成。

第一行包含两个数字,首先是输入进制(十进制表示),然后是用输入进制表示的输入数字。

第二行包含两个数字,首先是输出进制(十进制表示),然后是用输出进制表示的输入数字。

第三行为空白行。同一行内数字用空格隔开。

输入样例:

8
62 2 abcdefghiz
10 16 1234567890123456789012345678901234567890
16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 23 333YMHOUE8JPLT7OX6K9FYCQ8A
23 49 946B9AA02MI37E3D3MMJ4G7BL2F05
49 61 1VbDkSIMJL3JjRgAdlUfcaWj
61 5 dl9MDSWqwHjDnToKcsWE1S
5 10 42104444441001414401221302402201233340311104212022133030

输出样例:

62 abcdefghiz
2 11011100000100010111110010010110011111001001100011010010001

10 1234567890123456789012345678901234567890
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2

16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 333YMHOUE8JPLT7OX6K9FYCQ8A

35 333YMHOUE8JPLT7OX6K9FYCQ8A
23 946B9AA02MI37E3D3MMJ4G7BL2F05

23 946B9AA02MI37E3D3MMJ4G7BL2F05
49 1VbDkSIMJL3JjRgAdlUfcaWj

49 1VbDkSIMJL3JjRgAdlUfcaWj
61 dl9MDSWqwHjDnToKcsWE1S

61 dl9MDSWqwHjDnToKcsWE1S
5 42104444441001414401221302402201233340311104212022133030

5 42104444441001414401221302402201233340311104212022133030
10 1234567890123456789012345678901234567890

分析:

本题考察高精度和进制转换。普通的做法可以先将a进制转化为十进制,再通过除基取整法转化为b进制,由于是高精度运算,所以略显麻烦。更简单的思路是将a进制直接转换为b进制。具体的方法如下:

以四进制数123转化为5进制数为例。123 (4) /  5 ,第一位不够除,值乘以权重累加到第二位,即1 * 4 + 2 = 6,6除以5余1,同样将余数乘以权重累加到第三位1 * 4 + 3 = 7,7 / 5 = 1 ... 2,可以得到123 (4) /  5  = 11 ... 2所以转换为五进制的最后一位数为2,继续将11 (4) / 5 = 1 ... 0,然后1(4) / 5 = 0 ... 1。于是转换后的五进制数为102。

为了方便计算,我们需要将可能带有字母的输入先转化为数字依次存入向量,转换后的结果再从向量转成字母。之后直接按照上面转换的思路进行转换即可。注意,每次做完除法均需要将多余的零删掉,一开始就翻转保存数字的向量就只需删除末尾的0了,而且一次除法之后可能末尾多出不少0,需要用while而不是if进行判断。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
    int T;
    cin>>T;
    while(T--){
        int a,b;
        string a_line,b_line;
        cin>>a>>b>>a_line;
        vector<int> number;
        for(auto c : a_line){
            if(c >= '0' && c <= '9')    number.push_back(c - '0');
            if(c >= 'A' && c <= 'Z') number.push_back(c - 'A' + 10);
            if(c >= 'a' && c <= 'z')    number.push_back(c - 'a' + 36); 
        }
        reverse(number.begin(),number.end());//翻转方便删除元素
        vector<int> res;
        while(number.size()){
            int r = 0;
            for(int i = number.size() - 1;i >= 0;i--){
                number[i] += r * a;//加上高位留下来的权值
                r = number[i] % b;
                number[i] /= b;
            }
            res.push_back(r);
            while(number.size() && !number.back()) number.pop_back();//删除末尾多余的0
        }
        reverse(res.begin(),res.end());
        for(auto x : res){
            if(x <= 9)  b_line += char(x + '0');
            if(x >= 10 && x <= 35)  b_line += char(x - 10 + 'A');
            if(x >= 36) b_line += char(x - 36 + 'a');
        }
        cout<<a<<" "<<a_line<<endl;
        cout<<b<<" "<<b_line<<endl;
        cout<<endl;
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值