CCF-CSP 30次 第三题【解压缩】(stoi进制转换+bitset)

太复杂了,还没完全弄明白

第30次csp认证——前三题个人题解思路与反思_csp题解_Onerios的博客-优快云博客

计算机软件能力认证考试系统

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, idx, p; // 当前已经解压缩了 p 字节,下一个读的是第 idx 下标的字符
string res; // 解压后的数据

string readBytes(int num)
{
    char byte[2 * num];
    for (int i = 0; i < 2 * num; i ++) cin >> byte[i];
    idx += num * 2;
    return string(byte, 2 * num);
}

void trackBack(int o, int l)
{
    int start = res.length() - o * 2;
    int len = o * 2;
    string back_track_string = res.substr(start, len);
    int cnt = 0;
    while (cnt < l * 2 - l * 2 % len)
    {
        res += back_track_string;
        cnt += len;
    }
    res += back_track_string.substr(0, l * 2 % len);
}
int main()
{
    cin >> n;
    string bts;
    vector<int> c;
    int v_c;
    // 读入字节 直到最高位为0
    while ((bts = readBytes(1)) >= "80")
    {
        v_c = stoi(bts, nullptr, 16);
        v_c -= 128;
        c.push_back(v_c);
    }
    // 最高位为0时,直接保存到c里
    v_c = stoi(bts, nullptr, 16);
    c.push_back(v_c);
    // 引导区结束,计算原始数据长度
    int length = 0;
    for (int i = 0; i < c.size(); i ++) length += c[i] * pow(128, i);

    while (idx < n * 2)
    {
        // 接下来是数据域
        // 读入一个字节
        bts = readBytes(1);
        string string_to_binary = bitset<8>(stoi(bts, nullptr, 16)).to_string();
        string lowest_two_digits = string_to_binary.substr(6, 2);
        if (lowest_two_digits == "00")
        {
            string high_six_digits = string_to_binary.substr(0, 6);
            int ll = stoi(high_six_digits, nullptr, 2);
            // l <= 60,高六位 ll 表示 l - 1
            if (ll <= 59)
                res += readBytes(ll + 1);
            else
            {
                // 第一个字节的高六位存储的值为 60、61、62 或 63 时,分别代表 l - 1 用 1、2、3 或 4 个字节表示
                int literal_length = ll - 59;
                // 按照小端序重组字符串 0x01 0x0A => 0x0A01
                string string1 = readBytes(literal_length);
                string string2;
                // 字符串每两位反转
                for (int i = string1.length() - 2; i >= 0; i -= 2)
                    string2 += string1.substr(i, 2);
                int l = 1 + stoi(string2, nullptr, 16); // 字面量长度
                res += readBytes(l);
            }
        }
        else if (lowest_two_digits == "01")
        {
            // 第 2 ~ 4 位即 从下标 3 开始的三位 001 011 01
            string two_to_four_digits = string_to_binary.substr(3, 3);
            // l - 4 占 3 位,存储于首字节的 2 至 4 位中
            int l = stoi(two_to_four_digits, nullptr, 2) + 4;
            // o 占 11 位,其低 8 位存储于随后的字节中,高 3 位存储于首字节的高 3 位中
            string high_three_digits = string_to_binary.substr(0, 3);
            string next_byte_binary = bitset<8>(stoi(readBytes(1), nullptr, 16)).to_string();
            int o = stoi(high_three_digits + next_byte_binary, nullptr, 2);
            // 回溯引用
            trackBack(o, l);
        }
        else if (lowest_two_digits == "10")
        {
            string high_six_digits = string_to_binary.substr(0, 6);
            // l 占 6 位,存储于首字节的高 6 位中
            int l = stoi(high_six_digits, nullptr, 2) + 1;
            // o 占 16 位,以小端序存储于随后的两个字节中
            string string1 = readBytes(2);
            string string2;
            // 字符串每两位反转
            for (int i = string1.length() - 2; i >= 0; i -= 2)
                string2 += string1.substr(i, 2);
            int o = stoi(string2, nullptr, 16);
            // 回溯引用
            trackBack(o, l);
        }
    }
    for (int i = 0; i < res.length(); i ++)
    {
        cout << res[i];
        // 输出,每16个字符加一个换行
        if ((i + 1) % 16 == 0) cout << endl;
    }
    // 若最后一行不能凑8个,则补一个换行
    if (res.length() % 16) cout << endl;
    return 0;
}

 

### CCF-CSP 第35认证第三目分析与解法 关于CCF-CSP第35认证中的第三,目前公开的具体目描述尚未广泛传播于网络资源中[^1]。然而,基于以往CSP认证的特点以及考生反馈的信息,可以推测该类目通常考察的是编程基础能力和逻辑思维能力[^2]。 #### 可能涉及的知识点 此类目往往围绕以下几个方面展开: - **数据结构**:如数组、链表、栈、队列等基本操作。 - **算法设计**:包括但不限于贪心算法、动态规划、二分查找等常见方法。 - **字符串处理**:对于输入输出格式的要求较高,需注意边界条件和特殊情况下的行为。 下面给出一个假设性的例子来说明如何解答类似的竞赛问: 假定本是一个简单的区间覆盖或者路径优化问,则解决方案如下所示: ```cpp #include <bits/stdc++.++.h> using namespace std; int main(){ int n; cin >> n; // 输入n表示有多少个区域或节点 vector<pair<int, int>> intervals(n); for(auto &p : intervals){ cin >> p.first >> p.second; // 每组两个数代表起点终点坐标 } sort(intervals.begin(), intervals.end()); long long res = 0; int last_end = INT_MIN; for(const auto &[start,end]:intervals){ if(start>last_end){ res += end-start; last_end=end; } else{ if(end>=last_end){ res+=end-last_end; last_end=end; } } } cout<<res<<endl;// 输出最终结果即总长度或其他目标函数值 } ``` 上述代码片段展示了当面对连续区间的合并计算时的一种通用策略——通过排序并遍历所有给定区间实现最优求解过程[^3]。 #### 注意事项 在参加正式比赛前务必熟悉评测环境配置参数限制情况(时间复杂度O()要求),同时也要关注细节部分比如是否有负权边存在等问影响到具体实现方式的选择上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值