题目地址:
https://www.acwing.com/problem/content/description/126/
编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。这里有 62 62 62个不同数位 0 − 9 , A − Z , a − z {0−9,A−Z,a−z} 0−9,A−Z,a−z。
输入格式:
第一行输入一个整数,代表接下来的行数。
接下来每一行都包含三个数字,首先是输入进制(十进制表示),然后是输出进制(十进制表示),最后是用输入进制表示的输入数字,数字之间用空格隔开。
输入进制和输出进制都在
2
2
2到
62
62
62的范围之内。
(在十进制下)
A
=
10
,
B
=
11
,
…
,
Z
=
35
,
a
=
36
,
b
=
37
,
…
,
z
=
61
A=10,B=11,…,Z=35,a=36,b=37,…,z=61
A=10,B=11,…,Z=35,a=36,b=37,…,z=61 (
0
−
9
0−9
0−9仍然表示
0
−
9
0−9
0−9)。
输出格式:
对于每一组进制转换,程序的输出都由三行构成。
第一行包含两个数字,首先是输入进制(十进制表示),然后是用输入进制表示的输入数字。
第二行包含两个数字,首先是输出进制(十进制表示),然后是用输出进制表示的输入数字。
第三行为空白行。
同一行内数字用空格隔开。
可以先将输入按十进制的方式存入一个vector<int>
,从高位到低位存。需要注意的是,并不需要真的将输入转为十进制再存,每一位直接存
0
∼
62
0\sim 62
0∼62的数即可。例如,如果输入是ABC
,那直接存为
{
10
,
11
,
12
}
\{10,11,12\}
{10,11,12}即可,如果输入进制是
p
p
p,则
10
p
2
+
11
p
+
12
10p^2+11p+12
10p2+11p+12就是其十进制的真实数字。设输出进制是
q
q
q,本质上本题就是要让输入对
q
q
q做若干次带余除法,直到被除数变为
0
0
0,则余数的倒序即为所求。代码如下:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int ain, aout;
char get(int x) {
if (0 <= x && x < 10)
return '0' + x;
else if (10 <= x && x < 36)
return x - 10 + 'A';
else
return x - 36 + 'a';
}
// 让a表示的数对b做带余除法,商重新存入a,余数存入r
void div(vector<int>& a, int b, int& r) {
vector<int> c;
r = 0;
for (int i = 0; i < a.size(); i++) {
r = r * ain + a[i];
c.push_back(r / b);
r %= b;
}
// 将商的开头0全去掉。如果商是0的话,直接置a为空
int idx = 0;
while (idx < c.size() && !c[idx]) idx++;
a = vector<int>(c.begin() + idx, c.end());
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
string s;
scanf("%d%d", &ain, &aout);
cin >> s;
vector<int> a;
for (int i = 0; i < s.size(); i++) {
if ('0' <= s[i] && s[i] <= '9')
a.push_back(s[i] - '0');
else if ('A' <= s[i] && s[i] <= 'Z')
a.push_back(s[i] - 'A' + 10);
else
a.push_back(s[i] - 'a' + 36);
}
cout << ain << " " << s << endl;
cout << aout << " ";
string res;
int r;
// 只要商不是0,就进行循环
while (a.size()) {
div(a, aout, r);
res += get(r);
}
reverse(res.begin(), res.end());
cout << res << endl;
puts("");
}
}
时空复杂度取决于具体输入,只需注意向量 a a a表示的数字会以对数的速度变小,所以时间是很快的。