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;
}
相关推荐
蜡笔小马14 小时前
04.C++设计模式-桥接模式
c++·设计模式·桥接模式
jghhh0114 小时前
基于时差(TDOA)与 频差(FDOA) 的无源定位
算法
_深海凉_14 小时前
LeetCode热题100-回文链表
算法·leetcode·链表
pursuit_csdn14 小时前
力扣周赛 501
算法·leetcode·职场和发展
努力d小白14 小时前
leetcode70.爬楼梯
算法
AbandonForce14 小时前
LeetCode 滑动窗口个人思路详解
算法·leetcode·职场和发展
bnmoel14 小时前
数据结构深度剖析顺序表:结构、扩容与增删查改全解析
c语言·数据结构·算法·顺序表
Liangwei Lin14 小时前
LeetCode 45. 跳跃游戏 II
数据结构·算法·leetcode
宏笋14 小时前
C++ using typedef #define 三者的优缺点比较
c++
啦啦啦_999914 小时前
4. 决策树剪枝
算法·决策树·剪枝