题目描述
数据在传输过程中可能出错,因此接收方收到数据后通常会校验传输的数据是否正确,奇偶校验是经典的校验方式之一。
给定 n 个非负整数 c 1,c 2,…,c n代表所传输的数据,它们的校验码取决于这些整数在二进制下 1 的数量之和的奇偶性。如果这些整数在二进制下共有奇数个 1,那么校验码为 1;否则校验码为 0。你能求出这些整数的校验码吗?
输入格式
第一行,一个正整数 n,表示所传输的数据量。
第二行,n 个非负整数 ,c 1,c 2,…,c n表示所传输的数据。
输出格式
输出一行,两个整数,以一个空格分隔:
第一个整数表示 c 1,c 2,…,c n在二进制下 1 的总数量;
第二个整数表示校验码(0 或 1)。
输入输出样例 #1
输入 #1
71 69 83 80
输出 #1
13 1
输入输出样例 #2
输入 #2
6
1 2 4 8 16 32
输出 #2
6 0
说明/提示
对于所有测试点,保证 1≤n≤100,0≤c i≤255。
这道题的核心任务是两步:首先,统计所有输入数字在转换成二进制后,总共有多少个 1;然后,根据这个总数的奇偶性来确定一个校验码。
那么,关键就在于如何计算一个给定的十进制数 c 转换成二进制后有多少个 1 呢?我们可以利用循环和取余运算来模拟这个过程。只要这个数 c 还大于 0,我们就不断地重复两个操作:第一,用 c 对 2 取余数,如果余数是 1,就说明它二进制表示的这一位是 1,我们的计数器就应该加一。第二,将 c 整除以 2(c = c / 2)。我们持续这个过程,直到 c 变为 0 为止,这样就能准确地统计出所有 1 的个数了。
将所有数字的 1 的个数都累加起来,我们就得到了总数,根据总数的奇偶性和题意进行输出即可。
#include <cstdio>
using namespace std;
int n, v;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int c;
scanf("%d", &c);
while (c) {
v += c & 1;
c >>= 1;
}
}
printf("%d %d\n", v, v & 1);
return 0;
}