ISBN 号码

扫描 ISBN 的前九个数字计算带权和,再按模 11 规则校验或替换识别码。

OJ: shumeng

题目 ID: CSP201312B

难度:入门

标签:模拟

日期: 2026-07-31 16:21

形式化题目

输入格式正确的 ISBN 字符串 x-xxx-xxxxx-x,检查最后的识别码是否等于前九个数字按权重 1199 计算的和模 1111。余数 1010 要写成大写字母 X

正确时输出 Right;错误时只替换最后一位,原样输出带连字符的正确 ISBN。

思路

先按题面固定位置取出九个数字,直接套用校验公式:

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-31 16:21
 * update_at: 2026-08-17 22:45
 */
// brute.cpp:按 ISBN 固定格式逐位取出前 9 个数字,再直接套校验公式。
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string isbn;
    cin >> isbn;

    int positions[9] = {0, 2, 3, 4, 6, 7, 8, 9, 10};
    int sum = 0;
    for (int i = 0; i < 9; i++) {
        sum += (isbn[positions[i]] - '0') * (i + 1);
    }

    int remainder = sum % 11;
    char correct = remainder == 10 ? 'X' : char('0' + remainder);
    if (isbn[12] == correct) {
        cout << "Right\n";
    } else {
        isbn[12] = correct;
        cout << isbn << '\n';
    }

    return 0;
}

这个做法依赖格式中的固定下标。正式代码更稳妥:从左到右扫描字符串,忽略连字符,只对遇到的前九个数字累加 数字 × 第几个数字。最后用余数构造正确识别码,与 isbn.back() 比较即可。

识别码计算演示

下面展示样例 0-670-82162-4 的带权和计算:

位置 字符 权重 贡献
第 1 个数字 0 1 0
第 2 个数字 6 2 12
第 3 个数字 7 3 21
第 4 个数字 0 4 0
第 5 个数字 8 5 40
第 6 个数字 2 6 12
第 7 个数字 1 7 7
第 8 个数字 6 8 48
第 9 个数字 2 9 18

和为 158158158mod11=4158 \bmod 11 = 4,识别码应为 4,与输入一致所以输出 Right

注意识别码本身也可能是数字,但它不能参与带权和;因此只在读到前九个数字时累加。

代码

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-31 16:21
 * update_at: 2026-08-17 22:45
 */
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string isbn;
    cin >> isbn;

    int sum = 0;
    int digit_count = 0;
    // 只计算前 9 个数字,连字符不参与校验。
    for (int i = 0; i < (int)isbn.size(); i++) {
        if ('0' <= isbn[i] && isbn[i] <= '9') {
            digit_count++;
            if (digit_count <= 9) {
                sum += (isbn[i] - '0') * digit_count;
            }
        }
    }

    int remainder = sum % 11;
    char correct = remainder == 10 ? 'X' : char('0' + remainder);
    if (isbn.back() == correct) {
        cout << "Right\n";
    } else {
        isbn.back() = correct;
        cout << isbn << '\n';
    }

    return 0;
}

复杂度

字符串长度固定为 1313,时间复杂度和空间复杂度都为 O(1)O(1)

总结

固定格式模拟题最容易错在“哪些字符参与计算”。把连字符跳过,并明确限制只统计前九个数字,就能避免把最后的识别码重复算入。