1 条题解
-
0
题意分析
这道题是关于 ISBN 编号的校验和补全问题。已知 ISBN 是 10 位编码,其中前 9 位代表书籍,最后一位是校验位。校验规则是:把第 1 位数字乘 10、第 2 位乘 9、第 3 位乘 8…… 直到第 10 位乘 1,将所有结果相加后,这个总和必须能被 11 整除。现在输入的 ISBN 中恰好有一个位置是 '?',需要找出这个位置应该填什么数字(或 X)才能让 ISBN 有效,找不到合法解就输出 - 1。需要注意的是:前 9 位只能是 0-9 的数字,第 10 位如果是 10 的话要用 X 表示。
解题思路
1. 确定缺失位置
首先找到输入字符串中 '?' 的位置,记为 pos(从左到右数第 1 位到第 10 位)。比如输入 "15688?111X",'?' 在第 6 位。
2. 计算已知部分的校验和
遍历整个 ISBN 的每一位,遇到不是 '?' 的位置就计算它的贡献值:第 i 位(i 从 1 开始)的权重是 (11 - i),比如第 1 位权重是 10,第 2 位权重是 9,依此类推。如果是数字就直接乘权重累加;如果是第 10 位且字符是 X,就按 10 来计算。例如输入 "15688?111X",前 5 位和后 4 位(除了 '?')的数字乘对应权重相加,得到已知部分的和 sum。
3. 推导缺失位的可能值
假设缺失位的权重是 w(w = 11 - pos),缺失位需要填的数是 d。整个校验和必须能被 11 整除,即(已知和 sum + w×d)能被 11 整除。 如果缺失位在第 1-9 位:d 只能是 0-9 的数字。需要找到一个 d,使得(sum + w×d)是 11 的倍数,且 d 在 0-9 之间。
如果缺失位在第 10 位:d 可以是 0-9 或 10(对应 X)。此时 d=10 时要输出 X,否则输出数字,但 d 必须满足 0-10 的范围,并且(sum + w×d)能被 11 整除。
4. 验证并输出结果
计算满足条件的 d:
对于第 1-9 位的缺失位,先算 sum 除以 11 的余数 r,d 需要满足 (w×d) mod 11 = (11 - r) mod 11。解出 d 后,若 d 在 0-9 之间则输出,否则输出 - 1。
对于第 10 位的缺失位,同样算余数 r,d 的可能值是 (11 - r) mod 11。如果 d=10 就输出 X,d 在 0-9 之间就输出数字,否则输出 - 1。
代码
#include<iostream> using namespace std; int main() { char s[10]; while(cin>>s) { int i,flag,res=0; for(i=0;i<10;i++) { if(s[i]>='0'&&s[i]<='9')//是数字则乘其权值累加 res+=(s[i]-'0')*(10-i); else if(s[i]=='X')//是X则加10 res+=10; else if(s[i]=='?')//是?则记录其权值 flag=10-i; } for(i=0;i<=10;i++)//枚举?处数字 if((res+flag*i)%11==0) break; if(i==10) { if(flag!=1)//不存在可行解 cout<<"-1"<<endl; else//?是X cout<<"X"<<endl; } else cout<<i<<endl; } return 0; } ``` ```
- 1
信息
- ID
- 1191
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者