1 条题解

  • 0
    @ 2025-8-24 22:26:41

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 一扶苏一
    休息结束。邮箱 yifusuyi@qq.com

    搬运于2025-08-24 22:26:41,当前版本为作者最后更新于2020-12-01 19:03:17,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    P7106 双生独白

    Analysis

    众所周知,C/C++ 选手可以使用 scanf 直接读入 16 进制数字:scanf("%x", &a)

    对于输出 16 进制数字,可以使用 printf("%x", a)printf("%X", a),其中 x 的大小写控制的是输出十六进制中字母字符的大小写。例如 printf("%x %X", 10, 10); 的结果为 a A

    下一个问题是如何把读入割裂成三个数:可以先读入到字符数组里,然后使用 memcpy 把两个字符从数组中拷贝出来,再用 sscanf 从字符数组中读入数据,其使用方式为 scanf(A, B, ...),其中 A 表示目标数组,B 与后面的内容与 scanf 使用方法一致。例如,从字符数组 ss 中读入一个整数的写法是 scanf(s, "%d", &a)memcpy 的使用方式为 memcpy(t, s, x),其中 t 是拷贝的目标数组,s 是被拷贝位置的第一个指针,x 是被拷贝的字节数。例如,从从 s 中拷贝两个字符到 t 的写法是 memcpy(t, s, 2 * sizeof (char))

    字符数组的数组名本质上是一个指针,因此可以通过传入头指针的方式控制从哪一位开始读入/拷贝。例如 scanf(s + 1, "%d", &a) 表示从数组 ss 中第一位(下标从 0 编号)起进行读入,memcpy(t, s + i, 2 * sizeof(char)) 表示从第 ii 位起开始进行拷贝,拷贝两个字符。

    最后一个问题是,如果输出某个数的十进制值不超过 1515,那么输出结果会少一位,因此需要进行特判。好像有一些奇技淫巧可以避免这个问题,但是我并没有查到(。

    于是可以方便的写出如下代码:

    #include <cstdio>
    #include <cstring>
    
    char s[10];
    char t[3];
    
    int main() {
      scanf("%s", s);
      putchar('#');
      for (int i = 1; i < 6; i += 2) {
        int x;
        memcpy(t, s + i, 2 * sizeof(char));
        sscanf(t, "%x", &x);
        x = 255 - x;
        if (x < 16) putchar('0');
        printf("%X", x);
      }
      return 0;
    }
    

    upd:经过查阅资料,发现可以用 scanf("%2d", &a) 控制只读取两位数字,printf("%02d", a) 控制输出两位数字并补前导 00。因此可以写出更简短的代码如下:

    #include <cstdio>
    
    char s[10];
    
    int main() {
      scanf("%s", s);
      putchar('#');
      for (int i = 1, x; i < 6; i += 2) {
        sscanf(s + i, "%2x", &x);
        printf("%02X", 255 - x);
      }
      return 0;
    }
    
    • 1

    信息

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