UVA389 题解

· · 题解

大致题意

分析

作为典型的进制转化问题,非十进制转化为非十进制的常规方法是先把 b_1 进制转化为十进制,再转化为 b_2 进制。

1. b_1 进制转化为 10 进制

由于字符串 s 下标大的表示低位,下标小的表示高位,因此按照数字减去 48,字母减去 55 的办法将字符转化为数值后,依次乘以 b_1 的幂次即可。 参考代码:

for (int i = 0; i <= len1 - 1; i += 1)
{
    if (str[i] >= '0' && str[i] <= '9') b10value += (str[i] - 48ll) * p(b1, len1 - 1 - i);
    else if (str[i] >= 'A' && str[i] <= 'Z') b10value += (str[i] - 55ll) * p(b1, len1 - 1 - i);
}

2. 10 进制转化为 b_2 进制

为便于输出,我们可以使用下面的字符串事先数字、字母和数值 0\sim 36 的对应。输出时,使用 putcharprintf("%c") 输出对应的字符即可。

//使用一个字符串存储字符集, AtoZ表示10-35 
const char charset[40] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

转化过程中,重复“模 b_2 然后整除 b_2”的流程,再参考上面的序列将十进制数转化为由一系列字符组成的序列,然后倒序输出即可(因为重复这个流程,这个序列是从低位到高位依次排列的)。 参考代码:

for (int i = 0; i <= 7; i += 1)
{
    result[i] = charset[b10value % b2];
    b10value /= b2;
    if(b10value==0) break;
}
//空位补上空格
for (int i = 6; i >=0;i-=1) putchar(result[i]=='\0' ? ' ' : result[i]);

3. 注意事项

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
long long p(long long a, long long x)
{
    return x ? a * p(a, x - 1) : 1;
}
void kernel(void)
{
    char str[10], result[100] = { 0 };
    //使用一个字符串存储字符集, AtoZ表示10-35 
    const char charset[40] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    long long b1, b2, b10value = 0, len1, len2;
    if (scanf("%s%lld%lld", str, &b1, &b2) == EOF) exit(0);
    len1 = strlen(str);
    //b1进制数转化为10进制数
    for (int i = 0; i <= len1 - 1; i += 1)
    {
        if (str[i] >= '0' && str[i] <= '9') b10value += (str[i] - 48ll) * p(b1, len1 - 1 - i);
        else if (str[i] >= 'A' && str[i] <= 'Z') b10value += (str[i] - 55ll) * p(b1, len1 - 1 - i);
    }
    len2 = (long long)(log10(1.0 * b10value) / log10(1.0 * b2)) + 1;//对数换底公式确定b2进制有多长
    if (len2 >= 8)//超过7位报错
    {
        printf("  ERROR\n");
        return;
    }
    for (int i = 0; i <= 7; i += 1)
    {
        result[i] = charset[b10value % b2];
        b10value /= b2;
        if(b10value==0) break;
    }
    if(result[7])
    {
        printf("  ERROR\n");
        return;
    }
        //字符数组初始化为0, 要避免输出\0字符,应将未使用的空位替换为空格输出
    for (int i = 6; i >=0;i-=1) putchar(result[i]=='\0' ? ' ' : result[i]);
    putchar(10);
}

int main()
{
    while (1) kernel();
}

Extra

36 进制下,任何一个英文单词都可以转化为相应的十进制数(并且很可能会突破 unsigned __int64 的上限)。36 进制下,英文单词 ERROR 转化为十进制等于 24810219