夜雨聆风学习资料网

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;}

补充说明(易错点)

  1. 如果某个数字x某一位是0:不会执行cnt[k]++,数组保持原值,符合题意,没有出现的位视作0。
  2. 位编号k从0开始,和题目描述从右向左编号0、1、2完全匹配。
  3. 上限,最多30位左右,数组开32足够覆盖全部情况。
  4. 等价位运算写法: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位=1cnt[0]=3,cnt[2]=3,等于n=3,ans=2,输出2,和样例输出一致。

题解二:思路

核心思想:按位与&的性质:只有所有数的某一位全部为1,按位与结果的这一位才是1;只要有任意一个数该位是0,按位与结果这一位就变成0。

  1. 将所有数字依次做按位与运算,得到结果r。r里面为1的二进制位,就是全部n个数字都为1的位。
  2. 统计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)

  • ,,
  1. 初始 = 13
  2. r = 13 &7 = 0101(十进制5)
  3. r =5 &15 =0101(十进制5,二进制0101,第0位、第2位是1)
  4. 统计r=5二进制中1的数量,得到ans=2,输出2,和样例输出一致。

关键知识点

  1. 按位与&:全1出1,有0出0。多个数字连续按位与,最终结果保留的1,必须每一个数字这一位都是1。
  2. r & 1:取出整数二进制最低位,用来判断该位是否为1。
  3. r >> 1:二进制整体右移一位,相当于整数除以2,丢弃最低位。

两种解法对比

方案
思路
优点
缺点
方案1(cnt数组计数)
统计每一位出现1的次数,判断cnt[i]==n
容易理解,适合初学者,便于调试
需要开辟数组空间
方案2(连续按位与)
全部数字做&,统计结果中1的个数
代码简短,不需要数组,运行快
需要深刻理解按位与性质

边界测试点提醒

  1. 如果输入里面存在数字0:所有数按位与结果r=0,循环不执行,ans=0,输出0,正确;
  2. 数据范围,int可以存下,不会溢出。

相关学习资料