计算校验码

【问题描述】

传送一个B(B≤16)进制的数值N时,最后加上一个一位(B进制的)校验码,使得N加上校验位后能被B-1整除。比如十进制的数值123(10),其校验码就是3,因为十进制数值1233(10)能被9整除。16进制的数78(16),其校验码为0,因为16进制的780(16)是15的倍数。超过十进制后,用字母a表示10,字母b表示11,字母c表示12,字母d表示13,字母e表示14,字母f表示15。

告诉你进制B,以及一个B进制的正整数N,要求你计算正整数N在B进制下的校验码。

【输入形式】

输入第一行正整数t (10 ≤ n ≤ 100),表示有多少组测试数据。

后面有t行,每行两个正整数B,N(2≤ B≤16),中间用一个空格隔开,B是10进制整数,N用B进制形式表示。测试数据保证没有非法的B进制数N(也即N中每一位都是在0到B-1之间,没有前导0)。

40%的测试数据N的位数L 1 ≤ L≤ 10;

30%的测试数据N的位数L 1 ≤ L≤ 10(2);

20%的测试数据N的位数L 1 ≤ L≤ 10(3);

10%的测试数据N的位数L 1 ≤ L≤ 10(4);

【输出形式】

对于每组测试数据,输出一位占一行:正整数N在B进制下的校验码。(如果校验码可以为B-1,也可以为0,输出0)。

【样例输入】

4
10 123
16 78
16 1234321
12 ab

【样例输出】

3
0
e
1

【提示】:B进制的数能被B-1整除,当且仅当各位数字和能被B-1整除。

解题思路

  1. 理解校验码的定义:校验码的设计是为了使得原数N加上这个校验位后的新数能被B-1整除。这告诉我们需要找到一个合适的校验码,加到N的末尾,使得整体数值模B-1的结果为0。

  2. 利用性质简化问题:根据提示,一个B进制数能被B-1整除的充要条件是它各位数字的和能被B-1整除。因此,我们不需要关心N具体的数值,只需要关注N的各位数字之和。

  3. 计算各位数字之和:将N的各位数字相加得到一个和sum。

  4. 计算校验码:找到一个数字X(0 ≤ X < B),使得(sum + X)能被B-1整除。X即为所求的校验码。checkSum = (B - 1) - (sum % (B - 1));

  5. 处理特殊情况:如果校验码可以为B-1,也可以为0,根据题目要求,我们输出0。

核心逻辑是计算输入的B进制数N的校验码,使得将校验码加到N的末尾后,得到的新数能够被B-1整除。这里使用了字符串处理的方式来逐个读取B进制数N的每一位,并将其转换为十进制的数值进行计算。最后,通过对各位数值之和进行特定的计算,找到符合条件的校验码,并根据题目要求进行输出。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();

        while(t-- > 0){
            int B = scanner.nextInt(); // 读取进制B
            String N = scanner.next();  // 读取B进制数N,以字符串形式读入,便于逐字符处理

            int sum  = 0;  // 初始化变量sum用于存储N的各位数字之和
            for (int i = 0; i < N.length(); i++) {
                char c = N.charAt(i);
                int value; // 用于存储当前字符代表的数值
                // 判断当前字符是数字还是字母,并转换为对应的数值
                if(c >= '0' && c <= '9') value = c - '0'; // '0'到'9'之间的字符转换为0到9的数值
                    else value  = 10 + (c - 'a'); // 'a'到'f'之间的字符转换为10到15的数值
                sum += value;
            }

            // 计算校验码:(B - 1) - checkSum = (sum % (B - 1)),这里的目的是找到一个数X使得(S + X)能被B-1整除
            int checkSum = (B - 1) - (sum % (B - 1));
            // 如果计算出的校验码等于B-1,根据题目要求,将其替换为0
            if(checkSum == B-1) checkSum = 0;

            // 根据校验码的值输出对应的字符
            // 如果校验码大于9,需要转换为'a'到'f'之间的字母
            if(checkSum > 9) System.out.println((char)(checkSum - 10 + 'a'));
                else System.out.println(checkSum);
        }
        scanner.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值