题解:B3869 [GESP202309 四级] 进制转换

· · 题解

声明(也就是废话)

题目大意

输入 n 个整数与其进制 k,对于每一个整数,我们求它得十进制并输出。

分析

相信大家早就发现了,题目良心得给出了转换方法!
这里放上原文:

“对于任意一个 LK 进制数,假设其最右边的数位为第 0 位,最左边的数位为第 L-1 位,我们只需要将其第 i 位的数码乘以权值 K^i,再将每位的结果相加,即可得到原 K 进制数对应的十进制数。”

什么意思呢?

这里涉及到一个概念:位权。

什么是位权呢?我们拿一个十进制数 114514 举例:

类型 十万位 万位 千位 百位 十位 个位
数字 1 1 4 5 1 4
位权 10^5 10^4 10^3 10^2 10^1 10^0
计算过程 10^{5} \times 1 10^{4} \times 1 10^{3} \times 4 10^{2} \times 5 10^{1} \times 1 10^{0} \times 4
实际数值 100000 10000 4000 500 10 4

114514 就是每一位代表的实际数值之和。

相信大家有思路了吧!第 n 位的位权,就代表这一位上每一个 1 代表的数量。

这是十进制中的位权。但如果这个 114514 是八进制数呢?

类型 十万位 万位 千位 百位 十位 个位
数字 1 1 4 5 1 4
位权 8^5 8^4 8^3 8^2 8^1 8^0
计算过程 8^{5} \times 1 8^{4} \times 1 8^{3} \times 4 8^{2} \times 5 8^{1} \times 1 8^{0} \times 4
实际数值 32768 4096 2048 320 8 4

这几个数值加起来,刚好就是八进制数 114514 的十进制形式 39244

着手实现

看到这里,相信大家都明白怎么写代码了吧!但是还有几个易错点我要讲一讲。

如果你想用 int 类型输入,随后用 while 循环拆分数位累加的话,那你可就大错特错了。虽然用这种方式拆分数位又快又好用,但是你想过没有,int 类型似乎不支持除了 1~10 以外的数字输入啊!

而这些数字(包括但不限于 A)可是 11~16 以及更多进制的命根子!

我们只能用 string 来实现。当然,如果你学有余力,不妨挑战一下字符数组?

正所谓那句老话:

“十年 OI 一场空,不开 long long 见祖宗!”

我们可以想一下,如果题目输入十六进制数 \text{FFFFFFFFF} 怎么办?这个数非常大,会把 int 类型撑爆!就算是 long 类型也很危险!

只能开 long long 了对吧?

当然,如果题目数据再大一点,我们就不得不用到 __int128 了。

代码

#include <iostream>
#include <cmath>
using namespace std;

long long n;

long long k;

long long num[15];

string snum;

int main() {
    cin >> n;//处理输入

    while (n--) {
        cin >> k >> snum;//处理输入

        long long ans = 0;

        for (long long i = 0; i < snum.size(); i++) {
            if (!(snum[i] >= '0' && snum[i] <= '9')) {
                num[i] = snum[i]-'A'+10;
            } else {
                num[i] = snum[i]-'0';
            }
            ans = ans * k + num[i];
          //我们可以直接在处理字符的时候直接进行累加。
          //当然,更直接的做法就是不要num数组,直接处理完后累加。
        }

        cout << ans << endl;//记得输出!
    }
    return 0;
}

大家看看,AC的非常漂亮是不是?