CCF-CSP第41次认证第一题——平衡数

题目描述

小 P 在学习了位运算后,定义了如下"平衡数":

  • 对于一个正整数 aa,如果其二进制表示中 10 的个数相等,则称其为平衡数。

这里的二进制表示以 1 为最高位,即不考虑更高位用于补位的 0。例如,正整数 12 的二进制表示为 1100,包含两个 1 和两个 0。在实际存储中,更高位可能需要填 0 补位,如 00001100,在本题中无需考虑此种情况。

小 P 已经生成好了 n 个正整数 a1,a2,⋯,an​,试编程统计里面有多少个平衡数。

输入格式

从标准输入读入数据。

输入的第一行包含一个正整数 n,第二行包含空格分隔的 n 个正整数 a1,a2,⋯,an​。

输出格式

输出到标准输出。

输出一个整数,表示 a1,a2,⋯,an中平衡数的个数。

样例输入

复制代码
3
2 5 9

样例输出

复制代码
2

样例解释

2 的二进制表示为 10,是平衡数;

5 的二进制表示为 101,不是平衡数;

9 的二进制表示为 1001,是平衡数。

子任务

50% 的测试点满足:0<ai≤256;

全部的测试点满足:0<n≤100 且 0<ai≤109。

题解

判断数字是否为平衡数的方法:首先将数字转换为二进制,然后统计其中0和1的个数是否相等。以下是具体实现方案:

二进制转换方法

将十进制数转换为二进制数的步骤如下:

  1. 对原数进行模2运算
  2. 将结果从低位到高位依次记录
  3. 将所得数值倒序排列即为对应的二进制数

在实际操作中,我们无需获取完整的二进制表示,只需统计位数即可。这里使用临时变量temp:

  • 当模2结果为1时加1
  • 否则减1
  • 最终判断temp是否为0

位运算优化方案

采用异或(XOR)运算进行优化,通过五轮"对折"异或将32位整数的所有位信息压缩到最低位:

步骤 操作 效果
1 x ^= x >> 16 高16位与低16位异或 → 结果在低16位
2 x ^= x >> 8 高8位与低8位异或 → 结果在低8位
3 x ^= x >> 4 高4位与低4位异或 → 结果在低4位
4 x ^= x >> 2 高2位与低2位异或 → 结果在低2位
5 x ^= x >> 1 高1位与低1位异或 → 结果在最低位

最终通过!(x & 1)判断原始数字中1的个数是否为偶数。

示例演示

x = 13为例(二进制:1101,3个1):

复制代码
初始:  x = 0000 0000 0000 0000 0000 0000 0000 1101
第1轮: x ^ (x >> 16) → x不变
第2轮: x ^ (x >> 8) → x不变
第3轮: x ^ (x >> 4) → x不变
第4轮: x ^ (x >> 2) → x = ...0000 1110 (14)
第5轮: x ^ (x >> 1) → x = ...0000 1001 (9)
最终: !(x & 1) = false

代码如下

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int cnt,n,op;

bool check(int x){
    int temp=0;
    while(x){
        if(x%2)temp++;
        else temp--;
        x/=2;
    }
    return temp==0;
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>op;
        if(check(op))cnt++;
    }
    cout<<cnt;
}

给一个位运算优化的方法

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int cnt,n,op;

bool check(int x){
    cout<<sizeof(x)<<endl;  
    x=x^x>>16;
    x=x^x>>8;
    x=x^x>>4;
    x=x^x>>2;
    x=x^x>>1;
    return !(x&1);
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>op;
        if(check(op))cnt++;
    }
    cout<<cnt;
}
相关推荐
Zane199425 分钟前
暴力字符串匹配失配就要把文本指针往回拉,KMP凭什么能让它一直往前走
算法
Tim_101 小时前
【LeetCode】338、比特位计数
c++·算法·leetcode
木子算法1 小时前
不是重心也不是中点:费马—韦伯点、它的最优性条件与迭代求解
人工智能·算法·目标跟踪
程序员AlbertTu2 小时前
# Mantissa 使用教程 — Python 版与 C++ 版
c++·python·数值运算
Lazionr2 小时前
多态:从多种形态到运行时绑定
开发语言·c++
tryxr2 小时前
矩阵的几种基础变换
java·数据结构·算法·矩阵
mmmmath_32 小时前
LeetCode.028.找出字符串中第一个匹配项的
数据结构·算法·leetcode
别动我齐刘海2 小时前
ROS2 Jazzy + C++ 实战路线——ros2_control
c++·人工智能·python·opencv·机器学习·机器人·github
Selvaggia2 小时前
DMD(Distribution Matching Distillation,分布匹配蒸馏)
算法
Navigator_Z3 小时前
LeetCode //C - 1255. Maximum Score Words Formed by Letters
c语言·算法·leetcode