洛谷普及B3619 10 进制转 x 进制 和 B3620 x 进制转 10 进制

题目1: 10 进制转 x 进制

题目2: x 进制转 10 进制

题号1:B3619 

题号2:B3620 

难度:普及一

题目1分析

洛谷普及B3619 10 进制转 x 进制 和 B3620 x 进制转 10 进制_第1张图片

首先就需要万能的除基取余法

这个一定要掌握,该方法代码如下

int zhuan(long long num,int k)
{
	int n=0;
	while(num>0)
	{
		if(num % k < 10)
		a[n++] = (num % k)+'0';
		else
		a[n++] = (num % k)-10 + 'A';
		num /= k;
	}
	n--;
	return n;
}

这个是我最喜欢用的形式,形参是传入的长整型十进制数,和一个进制。返回值是具体多少位。

如果仔细看你会发现,这个函数虽然转换了进制,但是它是典型的会将得到的进制数反着来,但是,为什么我不在函数里面将之反过来,而是仅仅返回一个位数呢。

答案是:反着输出,或者反着应用就可以。

n = zhuan(x,k);
for(int i=n;i>=0;i--)
printf("%c",a[i]);

整体来看一下代码:

源代码

#include
#include
char a[1000];
int zhuan(long long num,int k)
{
	int n=0;
	while(num>0)
	{
		if(num % k < 10)
		a[n++] = (num % k)+'0';
		else
		a[n++] = (num % k)-10 + 'A';
		num /= k;
	}
	n--;
	return n;
}

int main()
{int n = 0,k;
long long x;
scanf("%lld %d",&x,&k);
n = zhuan(x,k);
for(int i=n;i>=0;i--)
printf("%c",a[i]);

return 0;
}

特别简便清晰,也不用我过多解释了,通过也是嘎嘎块。洛谷普及B3619 10 进制转 x 进制 和 B3620 x 进制转 10 进制_第2张图片

关于类似的题还有反过来的进制转化为十进制类型,在这简单提一下,同样也是只需要掌握一种基本转化算法就够用,我推荐中学阶段常用的权重次方累加法,看题

题目2分析

洛谷普及B3619 10 进制转 x 进制 和 B3620 x 进制转 10 进制_第3张图片

只需要理解 3541(8) ->   1*8^0 + 4*8^1+5*8^2+3*8^3

通常传入的是字符串,因为要储存高进制数,则就需要注意字符 到 数值 的转换

f (s[i] >= '0' && s[i] <= '9') {
            digit = s[i] - '0';
        } else {
            digit = s[i] - 'A' + 10;
        }
        if (digit >= x) {  // 非法字符检查
            printf("0\n");
            return 0;
        }

然后就是累加阶段

  dec += digit * (long long)pow(x, i);

话不多说上代码

#include 
#include 
#include 

int main() {
    int x;
    char s[20];
    scanf("%d\n%s", &x, s);
    int len = strlen(s);
    long long dec = 0;
    // 反转字符串,从低位开始处理
    for (int i = 0; i < len / 2; i++) {
        char temp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = temp;
    }
    for (int i = 0; i < len; i++) {
        int digit;
        if (s[i] >= '0' && s[i] <= '9') {
            digit = s[i] - '0';
        } else {
            digit = s[i] - 'A' + 10;
        }
        if (digit >= x) {
            printf("0\n");
            return 0;
        }
        dec += digit * (long long)pow(x, i);
    }
    printf("%lld\n", dec);
    return 0;
}

关于进制之间的转换其实还有很多方法,但是基础的除基取余法基本上就够用

算法知识拓展

数组存储余数(高效处理大数)

优化点
使用数组存储余数,避免频繁的字符串操作,适合处理大数

void decToBase(long long num, int base, char *result) {
    if (num == 0) {
        strcpy(result, "0");
        return;
    }
    
    int i = 0, isNegative = 0;
    if (num < 0) {
        isNegative = 1;
        num = -num;
    }
    
    char digits[200]; // 足够存储大数
    while (num > 0) {
        long long rem = num % base;
        digits[i++] = (rem < 10) ? (rem + '0') : (rem - 10 + 'A');
        num /= base;
    }
    
    if (isNegative) digits[i++] = '-';
    digits[i] = '\0';
    
    // 反转并复制到结果
    strcpy(result, strrev(digits));
}

递归实现(代码简洁)

原理
递归调用自身处理高位余数,最终拼接结果。

void decToBaseRecursive(int num, int base, char *result, int *index) {
    if (num == 0) return;
    
    int rem = num % base;
    decToBaseRecursive(num / base, base, result, index);
    result[(*index)++] = (rem < 10) ? (rem + '0') : (rem - 10 + 'A');
}

void decToBase(int num, int base, char *result) {
    if (num == 0) {
        strcpy(result, "0");
        return;
    }
    
    int index = 0;
    if (num < 0) {
        result[index++] = '-';
        num = -num;
    }
    
    decToBaseRecursive(num, base, result, &index);
    result[index] = '\0';
}

位运算优化(高效处理二进制 / 十六进制)

原理
利用位运算快速提取每一位的值,适合二进制、十六进制等 2 的幂次进制。

void decToBinary(int num, char *result) {
    if (num == 0) {
        strcpy(result, "0");
        return;
    }
    
    int i = 0, isNegative = 0;
    if (num < 0) {
        isNegative = 1;
        num = -num;
    }
    
    while (num > 0) {
        result[i++] = (num & 1) ? '1' : '0';
        num >>= 1;
    }
    
    if (isNegative) result[i++] = '-';
    result[i] = '\0';
    strrev(result);
}

使用库函数(最简方案)

原理
利用 sprintf 或 snprintf 直接格式化输出进制字符串。

void decToBase(int num, int base, char *result) {
    if (base == 2) {
        snprintf(result, 33, "%s%b", (num < 0) ? "-" : "", num);
    } else if (base == 8) {
        snprintf(result, 12, "%s%o", (num < 0) ? "-" : "", num);
    } else if (base == 16) {
        snprintf(result, 11, "%s%X", (num < 0) ? "-" : "", num);
    } else {
        strcpy(result, "不支持的进制");
    }
}

洛谷普及B3619 10 进制转 x 进制 和 B3620 x 进制转 10 进制_第4张图片

你可能感兴趣的:(算法,数据结构,c语言,开发语言,c++)