ARTICLE · 1121158
GESP2026 年 9 月 C++ 三级真题|公共二进制位,数组统计 VS 按位与解法全解析
GESP2026 年 9 月 C++ 三级真题|公共二进制位,数组统计 VS 按位与解法全解析样例模拟:输入
GESP2026 年 9 月 C++ 三级真题:编程题一
公共二进制位
时间限制:1.0 s
内存限制:512.0 MB
题目描述
小红有 个非负整数 。她将每个整数转换为二进制后,想知道有多少个二进制位在所有整数中均为 。
二进制位从右向左编号为 。若某个整数的二进制表示中没有第 位,则认为它的第 位为 。
请你求出满足条件的二进制位数量。
输入格式
第一行一个整数 ,表示整数的个数。 第二行 个非负整数 。
输出格式
输出一个整数,表示所有整数的二进制表示中均为 的二进制位数量。
样例输入1
313715样例输出1
2样例解释1
三个整数二进制分别为 、 和 。 其中第 位和第 位均为 ,因此答案为 。
数据范围
题解一:思路
题目要求统计:所有数字二进制中,全部数字该位都为1的位的总个数。
思路:开数组cnt,cnt[k]记录第k个二进制位上等于1的数字一共有多少个。遍历每一个数字,拆解其二进制每一位,如果某一位是1,就把对应cnt[k]加1。全部处理完后,如果cnt[i]==n,说明全部n个数这一位都是1,答案计数+1。
小技巧:一个数最大,二进制不会超过32位,数组开32足够。
#include<iostream>usingnamespacestd;intmain(){// cnt数组:cnt[k]统计第k位二进制上为1的数字总个数int n,x,cnt[32]={0},k=0;cin>>n; //读入数字总个数for(int i=1;i<=n;i++){cin>>x; //读取当前处理的数字 k=0; //k代表二进制位编号,从0开始(最低位)while(x>0){// x%2取当前二进制最低位,如果等于1,该位计数+1if(x%2==1){ cnt[k]++; } k++; //准备处理下一位(向左移动一位) x=x/2; //整数除以2等价二进制右移一位,丢弃已经处理完的最低位 } }int ans=0;//遍历全部32个二进制位for(int i=0;i<32;i++){// 如果第i位上1的数量等于n,说明所有数字这一位全是1if(cnt[i]==n){ ans++; } }cout<<ans;return0;}补充说明(易错点)
如果某个数字x某一位是0:不会执行 cnt[k]++,数组保持原值,符合题意,没有出现的位视作0。位编号 k从0开始,和题目描述从右向左编号0、1、2完全匹配。上限,最多30位左右,数组开 32足够覆盖全部情况。等价位运算写法: x%2等价x&1;x=x/2等价x >>=1。
样例模拟:输入3 13 7 15
13二进制:1101 → 第0位=1,第2位=1 7二进制:0111 → 第0位=1,第1位=1,第2位=1 15二进制:1111 → 第0,1,2,3位=1 cnt[0]=3,cnt[2]=3,等于n=3,ans=2,输出2,和样例输出一致。
题解二:思路
核心思想:按位与
&的性质:只有所有数的某一位全部为1,按位与结果的这一位才是1;只要有任意一个数该位是0,按位与结果这一位就变成0。
将所有数字依次做按位与运算,得到结果 r。r里面为1的二进制位,就是全部n个数字都为1的位。统计 r的二进制里面1的总个数,就是本题答案。
对比上一种解法:不需要开cnt计数数组,利用按位与特性直接筛选出公共全1位,代码更简短,效率更高。
#include<bits/stdc++.h>usingnamespacestd;intmain(){int n,x,r; // n数字个数;x读入每个数字;r保存所有数连续按位与的结果cin>>n;for(int i=1;i<=n;i++){cin>>x;if(i==1){ r=x; // 第一个数,直接赋值给r,作为按位与初始值 }else{ r = r&x; // 将r和当前数字x按位与,等价 r &= x; } }int ans=0;// 统计r的二进制中1的总位数while(r>0){if(r&1>0){ // r&1取出r的最低位,如果最低位是1,答案+1 ans++; } r=r>>1; // 右移1位,等价 r >>= 1; 丢掉已经检查完的最低位 }cout<<ans;return0;}样例模拟(样例输入:3,13 7 15)
,,
初始 = 13 r = 13 &7 = 0101(十进制5) r =5 &15 =0101(十进制5,二进制 0101,第0位、第2位是1)统计 r=5二进制中1的数量,得到ans=2,输出2,和样例输出一致。
关键知识点
按位与 &:全1出1,有0出0。多个数字连续按位与,最终结果保留的1,必须每一个数字这一位都是1。r & 1:取出整数二进制最低位,用来判断该位是否为1。r >> 1:二进制整体右移一位,相当于整数除以2,丢弃最低位。
两种解法对比
cnt[i]==n | |||
&,统计结果中1的个数 |
边界测试点提醒
如果输入里面存在数字 0:所有数按位与结果r=0,循环不执行,ans=0,输出0,正确;数据范围,int可以存下,不会溢出。