1 条题解

  • 0
    @ 2025-5-22 19:46:44

    分析题意与解题方法

    题目背景

    题目要求实现一个程序,从输入中解析一组十六进制数,并根据特定规则生成一个新的十六进制值 KK。程序需要处理多个测试样例,每个样例包含 9 个十六进制数。


    输入格式

    1. 第一行是一个整数 SS,表示测试样例的数量。
    2. 对于每个测试样例:
      • 第一行包含若干个十六进制字符串,这些字符串可能未满 9 个。
      • 如果不足 9 个,则后续行继续读取,直到凑齐 9 个十六进制字符串为止。

    输出格式

    对于每个测试样例,输出一个十六进制值 KK


    解题思路

    1. 数据解析

    • 使用 split 函数将输入的字符串按空格分割成多个十六进制字符串。
    • 如果某行提供的十六进制数不足 9 个,则通过后续行补充,直到达到 9 个。

    2. 十六进制转换

    • 使用 hexToUL 函数将每个十六进制字符串转换为无符号长整型值。
    • 确保所有输入的十六进制字符串有效,否则程序退出。

    3. 核心算法

    目标

    生成一个新的十六进制值 KK,其每一位由以下规则决定:

    • 考虑输入的 9 个十六进制数的二进制位(从最低位到最高位依次编号为 0 到 31)。
    • 对于每一位:
      • 统计前 8 个数在该位上的值之和。
      • 将该和与第 9 个数在该位上的值进行比较。
      • 根据比较结果决定 KK 在该位上的值。

    规则详解

    1. 初始化变量 carry=0carry = 0,用于记录进位。

    2. 遍历每一位 i[0,31]i \in [0, 31]

      • 获取第 9 个数在第 ii 位的值 c9_bit=(nums[8]>>i)&1c9\_bit = (nums[8] >> i) \& 1
      • 统计前 8 个数在第 ii 位的值之和 sum_csum\_c
      • 计算总和 total=sum_c+carrytotal = sum\_c + carry
      • 判断当前位是否满足规则:
        • 如果 total%2==c9_bittotal \% 2 == c9\_bit,则 KK 的第 ii 位为 0。
        • 否则,KK 的第 ii 位为 1,并调整 total=(8sum_c)+carrytotal = (8 - sum\_c) + carry
      • 更新 carry=total/2carry = total / 2
      • KK 的第 ii 位设置为当前计算结果。
    3. 最终将 KK 转换为十六进制输出。


    示例代码分析

    关键函数解释

    1. split 函数

      • 功能:将输入字符串按空格分割为多个子串。
      • 实现:利用 istringstream 和循环逐次提取子串。
    2. hexToUL 函数

      • 功能:将十六进制字符串转换为无符号长整型值。
      • 实现:使用 strtoul 函数,若输入无效则退出程序。
    3. solve 函数

      • 功能:处理每个测试样例,生成对应的 KK 值。
      • 实现:
        • 读取输入并解析为 9 个十六进制数。
        • 按位计算 KK 的每一位。
        • 输出最终结果。

    示例运行

    输入

    2
    F F F F F F F F F
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    

    输出

    FFFFFFFF
    FFFFFFFF
    

    标程

    #include <iostream>
    #include <string>
    #include <vector>
    #include <sstream>
    #include <iomanip>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    vector<string> split(const string &s) {
        vector<string> tokens;
        string token;
        istringstream tokenStream(s);
        while (tokenStream >> token) {
            tokens.push_back(token);
        }
        return tokens;
    }
    
    unsigned long hexToUL(const string &s) {
        char *endptr;
        unsigned long value = strtoul(s.c_str(), &endptr, 16);
        if (*endptr != '\0') {
            cerr << "Invalid hex number: " << s << endl;
            exit(1);
        }
        return value;
    }
    
    void solve() {
        string line;
        getline(cin, line);
        int S = atoi(line.c_str());
    
        for (int s = 0; s < S; ++s) {
            getline(cin, line);
            vector<string> hexNumbers = split(line);
            while (hexNumbers.size() < 9) {
                getline(cin, line);
                vector<string> additionalNumbers = split(line);
                hexNumbers.insert(hexNumbers.end(), additionalNumbers.begin(), additionalNumbers.end());
            }
    
            unsigned int nums[9];
            for (int i = 0; i < 9; ++i) {
                nums[i] = hexToUL(hexNumbers[i]);
            }
    
            unsigned int K = 0;
            int carry = 0;
    
            for (int i = 0; i < 32; ++i) {
                bool c9_bit = (nums[8] >> i) & 1;
                int sum_c = 0;
    
                for (int j = 0; j < 8; ++j) {
                    sum_c += ((nums[j] >> i) & 1);
                }
    
                int total = sum_c + carry;
                bool bit = (total % 2) == c9_bit;
                int ki = bit ? 0 : 1;
    
                if (ki == 1) {
                    total = (8 - sum_c) + carry;
                }
    
                K |= (ki << i);
                carry = total / 2;
            }
    
            cout << hex << K << endl;
        }
    }
    
    int main() {
        solve();
        return 0;
    }
    

    总结

    该程序的核心在于:

    1. 数据的正确解析与验证。
    2. 对每一位的精确计算,结合进位逻辑生成 KK
    3. 输出格式符合题目要求。
    • 1

    信息

    ID
    1145
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    11
    已通过
    1
    上传者