当前位置:首页 > 洛谷 > 标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)

标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)

6个月前 (06-21)


标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)  进制转换算法 大数处理 代码优化 AC100 C++ 第1张

一、题目解读

洛谷B3617题要求将输入的八进制字符串转换为十六进制表示。题目需处理大数场景,且对输入合法性有明确限制(长度不超过1000,仅包含0-7字符)。由于八进制与十六进制无法直接转换,需借助十进制作为中间桥梁,因此解题思路需设计两步转换:八进制→十进制→十六进制。

二、解题思路

参考代码采用分模块设计,核心逻辑分为三部分:

    1. 输入验证:自定义isValidOctal()函数通过字符遍历与长度检查,过滤非法输入。

    2. 八进制转十进制:采用模拟乘法原理,每次将十进制结果乘以8并累加当前八进制位,通过字符串逆序处理实现大数乘法。

    3. 十进制转十六进制:利用短除法思想,从低位到高位逐位计算余数并拼接十六进制字符,最终逆序输出结果。

三、解题步骤

1. 预处理:读取用户输入的八进制字符串,调用isValidOctal()验证合法性。

2. 阶段一转换:通过octalToDecimal()函数实现八进制→十进制转换,关键步骤为循环迭代每位数字,模拟“乘8+本位”的竖式乘法过程。

3. 阶段二转换:调用decimalToHex(),将十进制数逐位除以16取余数,反向构建十六进制字符串。

4. 输出优化:针对0值特判,避免空字符串输出。

四、代码与注释

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

// 验证八进制字符串合法性
bool isValidOctal(const string& s) {
    if(s.empty() || s.length() > 1000) return false;  // 长度检查
    for(char c : s) {                              // 遍历字符
        if(c < '0' || c > '7') return false;        // 仅允许0-7
    }
    return true;
}

// 八进制转十进制(大数处理)
string octalToDecimal(const string& octal) {
    string decimal = "0";
    for(char c : octal) {
        int digit = c - '0';                      // 提取当前八进制位
        // 十进制数乘以8
        string temp = decimal;
        int carry = 0;
        for(int i = temp.length()-1; i >= 0; i--) { // 逆序处理大数乘法
            int num = (temp[i] - '0') * 8 + carry;
            temp[i] = (num % 10) + '0';            // 取个位
            carry = num / 10;                      // 进位
        }
        if(carry > 0) {
            temp.insert(0, 1, carry + '0');       // 前置最高位进位
        }
        // 加上当前八进制位
        carry = digit;
        for(int i = temp.length()-1; i >= 0 && carry > 0; i--) {
            int num = (temp[i] - '0') + carry;
            temp[i] = (num % 10) + '0';
            carry = num / 10;
        }
        if(carry > 0) {
            temp.insert(0, 1, carry + '0');
        }
        decimal = temp;
    }
    return decimal;
}

// 十进制转十六进制(大数处理)
string decimalToHex(const string& decimal) {
    if(decimal == "0") return "0";                  // 特判0值
    
    string hex;
    string num = decimal;
    const string hexDigits = "0123456789abcdef";    // 十六进制字符表

    while(num!= "0") {
        int remainder = 0;
        string temp;
        // 模拟除法过程
        for(char c : num) {
            int digit = remainder * 10 + (c - '0');  // 当前位乘以10 + 余数
            remainder = digit % 16;                 // 取余数
            digit /= 16;                            // 商
            if(!temp.empty() || digit > 0) {         // 非空或高位存在时拼接
                temp.push_back(digit + '0');
            }
        }
        hex.push_back(hexDigits[remainder]);        // 添加十六进制字符
        num = temp.empty()? "0" : temp;            // 更新被除数
    }
    
    reverse(hex.begin(), hex.end());                // 逆序输出结果
    return hex;
}

int main() {
    string octal;
    cin >> octal;                                  // 输入八进制串
    if(isValidOctal(octal)) {                      // 验证合法性
        string decimal = octalToDecimal(octal);    // 转十进制
        string hex = decimalToHex(decimal);       // 转十六进制
        cout << hex << endl;                       // 输出结果
    } else {
        cout << "Invalid input" << endl;           // 报错
    }
    return 0;
}

五、总结

本解法通过模块化设计实现了高效的大数进制转换,核心优势在于:

    1. 避免高精度库依赖,通过字符串模拟实现任意长度运算;

    2. 采用“乘8逐位累加”与“短除法逆向构建”算法,兼顾效率与可读性;

    3. 特判0值、长度验证等细节提升程序鲁棒性。

该思路适用于类似进制转换场景,为处理大数问题提供了通用模板。


原创内容 转载请注明出处

分享给朋友:

相关文章

征服力扣704题:三步掌握经典二分查找算法

征服力扣704题:三步掌握经典二分查找算法

题目重解我们面对的是算法领域最经典的二分查找问题:在一个已排序的整数数组中,快速定位目标值的位置。就像在一本按字母顺序排列的字典中查找单词,我们不需要逐页翻阅,而是通过不断折半的方式快速缩小搜索范围,...

力扣144:递归之美 轻松掌握二叉树前序遍历

力扣144:递归之美 轻松掌握二叉树前序遍历

题目解读二叉树的前序遍历是一种基础但重要的树遍历方式,其遍历顺序为:先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。给定一个二叉树的根节点,我们需要按照这个顺序访问所有节点,并将它们...

洛谷2181题解析:组合数学中顶点交点的计算与代码优化

洛谷2181题解析:组合数学中顶点交点的计算与代码优化

一、题目解读洛谷2181题要求计算n个顶点中任意选择4个顶点确定的交点数量。题目核心在于组合数学的应用,需通过排列组合公式推导结果,同时注意处理大数以避免溢出问题。理解题目中的“交点”定义(由4个顶点...

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

一、题目解读力扣3112题要求解决带时间限制的最短路径问题:给定一个有向图,节点具有消失时间,需计算从起点到各节点的最短路径,且路径总时间不能超过节点的消失时间。题目难点在于需在传统最短路径算法(如D...

牛客NC67题解:汉诺塔递归算法与解题步骤

牛客NC67题解:汉诺塔递归算法与解题步骤

一、题目解读牛客NC67题要求解决汉诺塔问题,这是一个经典的递归算法题目。题目给定整数n,代表汉诺塔中的盘子数量,需要输出将n个盘子从起始柱移动到目标柱的所有步骤。汉诺塔问题规则为:每次只能移动一个盘...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。