题解 | #[NOIP2008]ISBN号码#

[NOIP2008]ISBN号码

http://www.nowcoder.com/practice/95712f695f27434b9703394c98b78ee5

我采用的是模块化设计,将本题分解成了几个块,拼接在一起完成了本题.
以下有说不对的地方,敬请指出😅😅

首先,我们看到题目非常长,所以要提炼题目精华,粗略一扫得出
ISBN码包括9位数字        1位识别码和3位分隔符       规定格式如“x-xxx-xxxxx-x”       “-”是分隔符,最后一位是识别码
识别码的计算方法如下:
用所得的结果mod 11     所得的余数即为识别码        果余数为10,则识别码为大写字母X
编写程序判断输入的ISBN号码中识别码是否正确,如果正确,仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。

虽然还是有点多     ,但大概意思是 一串数    ,最后一位是识别码(我理解为校验位),      识别方式为    第一位*1+...+第九位*9 的和(权重)     对 11    取余(校验方式)
再判断校验是否正确,正确返回"Right" ,否则返会正确的这一串数(修正校验位);

题目意思懂了,那首先考虑怎么将这一串数分解出来,如果用暴力法也可以,将每一位数字都设置一个变量,但我偏不.
那太low了,编程编的不让别人看得懂都不好意思了.所以我采用了每一个间隔符前的所有数为一个整形
int a, b, c;
char x, x1;
scanf("%d-%d-%d-%c", &a, &b, &c, &x);
注: 最后一位为字符,因为 10 = X 所以将最后的识别码转为字符将是最后对比的重中之重



然后,开始考虑怎么将 第一位*1+...+第九位*9 的和 求出,因为我把这一串数拆分成了四个整形,所以方便我对每一个整形
进行修改
于是,我想到了设计一个函数来求出这个整形的和,再将三个整形(最后一个是标识符)的和加在一起就是 第一位*1+...+第九位*9 的和 
设计这个函数需要  一个数(a,b,c) 和 它的权重(1,2~4,5~9) 暂定这两个.
//      数据    权重
int fin(int number, int dis) { //每位乘
    if (number != 0)
        return fin(number / 10, dis + 1) + number % 10 * dis;
    else
        return 0;
}
我用的是递归的写法 但是我发现这样写虽然简单,但是求出的和却不是我想要的, 因为题目是从左向右乘以权重的,而我是从右到左
所以需要翻转数字(你以为我会重写??开玩笑😎😎)
于是...
//       数据      
int renum(int number) { //反转数字
    int result = 0, num = number;
    while (num) {
        result = result * 10 + num % 10;
        num /= 10;
    }
    return result;
}
将这两个结合就可以完成  第一位*1+...+第九位*9的和

接下来将求出的标识符存放在 X1
x1 = (a * 1 + fin(renum(b), 2) + fin(renum(c), 5)) % 11;
但此时x1为整形,还不能与x(识别码)做对比,因此再做一下判断,因为x可能是'X'(10)
x1 = x1 == 10 ? 'X' : x1 + '0';
注:一个整形加上'0'就可以变成对应的字符(int->char,0~9)
1 + '0' = '1'
9 + '0' = '9'

接下来做判断就可以了
if (x == x1)
        printf("Right");
    else
        printf("%d-%d-%d-%c", a, b, c, x1);

完整代码
#include <stdio.h>
//           数据      
int renum(int number) { //反转数字
    int result = 0, num = number;
    while (num) {
        result = result * 10 + num % 10;
        num /= 10;
    }
    return result;
}
//          数据      权重
int fin(int number, int dis) { //每位乘
    if (number != 0)
        return fin(number / 10, dis + 1) + number % 10 * dis;
    else
        return 0;
}
int main() {
    int a, b, c;
    char x, x1;
    scanf("%d-%d-%d-%c", &a, &b, &c, &x);
    x1 = (a * 1 + fin(renum(b), 2) + fin(renum(c), 5)) % 11;
    x1 = x1 == 10 ? 'X' : x1 + '0';
    if (x == x1)
        printf("Right");
    else
        printf("%d-%d-%d-%c", a, b, c, x1);

    return 0;
}









全部评论
作者,不需要翻转数字,你直接把dis的输入值改一下,再把dis+1改为dis-1就可以了吧?
3 回复 分享
发布于 2023-12-14 19:35 北京
6
2 回复 分享
发布于 2023-08-18 15:56 云南
学习了学习了
1 回复 分享
发布于 2024-12-18 21:23 湖南
受教了
点赞 回复 分享
发布于 03-06 11:11 江苏

相关推荐

评论
46
3
分享

创作者周榜

更多
牛客网
牛客企业服务