当前位置:首页 > GESP > 洛谷B3870题:位操作与二进制转换解决变长编码

洛谷B3870题:位操作与二进制转换解决变长编码

5小时前

洛谷B3870题:位操作与二进制转换解决变长编码 洛谷题解 进制转换 位运算 C++ GESP GESP四级 第1张

一、题目解读

洛谷B3870题要求将给定的无符号长整型数转换为可变长度的字节编码,并输出其十六进制表示。题目核心在于设计一种高效的编码方案,需处理数字的二进制位分组、最高位标记及字节顺序反转等细节。该问题考察对二进制位操作的理解与算法逻辑的严谨性,尤其在边界条件(如0的特殊编码)与分组补位机制上的实现。

二、解题思路

1. 二进制转换与去前导0:自定义toBinaryString函数将数字转为二进制串,通过倒序取余法生成,并去除前导0(避免无效位)。

2. 分组与最高位标记:将二进制串按7位分组,不足位补0。通过makeByte函数生成字节,非最后一组设置最高位为1,区分数据段与结束标志。

3. 字节反转输出:因处理从低位开始,最终需反转字节顺序,确保正确解码顺序。

4. 边界处理:0的特殊情况单独编码为单字节0,避免空输出。

三、解题步骤

1. 输入数字N:通过cin获取用户输入的无符号长整型数。

2. 二进制转换:调用toBinaryString(N)生成二进制串,去除前导0。

3. 分组编码:

○ 从末尾开始,每次取最长7位子串(不足补0)。

○ 通过makeByte将子串转为字节,根据位置标记最高位。

○ 存入bytes容器,记录编码结果。

4. 字节反转:使用reverse函数反转字节顺序,确保高位在前。

5. 输出十六进制:循环遍历字节,按格式%02X输出,空格分隔。

四、代码与注释

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

// 将数字转换为二进制字符串(去除前导0)
string toBinaryString(unsigned long long n) {
    if (n == 0) return "0"; // 0的特殊处理
    string binary;
    while (n > 0) {
        binary += (n % 2) + '0'; // 倒序取余生成二进制
        n /= 2;
    }
    reverse(binary.begin(), binary.end()); // 反转成正确顺序
    return binary;
}

// 将7位二进制字符串转换为字节(添加最高位)
char makeByte(const string& bits, bool isLast) {
    char byte = 0;
    for (int i = 0; i < 7; ++i) {
        char bit = (i < bits.size())? bits[i] - '0' : 0; // 不足位补0
        byte |= bit << (6 - i); // 按位左移拼接
    }
    if (!isLast) byte |= 1 << 7; // 非末尾组最高位设为1
    return byte;
}

// 主处理函数
vector<char> encodeNumber(unsigned long long n) {
    vector<char> bytes;
    if (n == 0) {
        bytes.push_back(0); // 0编码为单字节0
        return bytes;
    }
    
    string binary = toBinaryString(n);
    int len = binary.length();
    int pos = len;
    
    while (pos > 0) {
        int start = max(0, pos - 7); // 从末尾开始取7位组
        string group = binary.substr(start, pos - start);
        pos = start;
        
        // 补足7位
        while (group.length() < 7) {
            group = "0" + group;
        }
        
        bool isLast = (pos == 0);
        bytes.push_back(makeByte(group, isLast));
    }
    
    // 反转字节顺序(因处理从低位开始)
    reverse(bytes.begin(), bytes.end());
    return bytes;
}

int main() {
    unsigned long long N;
    cin >> N;
    
    vector<char> encoded = encodeNumber(N);
    
    // 输出十六进制表示
    for (size_t i =  encoded.size(); i >0; i--) {
        if (i!= encoded.size()) cout << " ";
        printf("%02X", (unsigned char)encoded[i-1]); // 强制类型转换避免警告
    }
    cout << endl;
    
    return 0;
}

五、总结

该解法通过模块化函数(二进制转换、字节生成、主逻辑)实现清晰编码流程,兼顾效率与边界处理。核心技巧在于:

● 二进制倒序生成避免额外反转操作;

● 分组补位与最高位标记简化解码逻辑;

● 字节反转确保大端序输出。

适用于需处理变长二进制数据的场景,算法简洁且易于扩展。未来可探索更紧凑的位运算优化,或结合动态规划优化分组效率。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣第654题:最大二叉树解题教程 用数组构造最大二叉树

力扣第654题:最大二叉树解题教程 用数组构造最大二叉树

题目解读给定一个不含重复元素的整数数组,我们需要构建一棵最大二叉树。构建规则是:数组中的最大值作为根节点,其左侧子数组构建左子树,右侧子数组构建右子树,然后递归地应用这个规则。这种构建方式体现了分治思...

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

2025年GESP七级等价消除(洛谷P11965)代码解析与优化策略

2025年GESP七级等价消除(洛谷P11965)代码解析与优化策略

一、题目解读    2025年GESP七级考试中的“等价消除(洛谷P11965)”问题要求统计给定字符串中满足等价条件的子串数量。所谓“等价子串”,是指子串中所...

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

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

一、题目解读洛谷B3617题要求将输入的八进制字符串转换为十六进制表示。题目需处理大数场景,且对输入合法性有明确限制(长度不超过1000,仅包含0-7字符)。由于八进制与十六进制无法直接转换,需借助十...

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

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

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

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

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

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

发表评论

访客

看不清,换一张

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