二进制枚举

如果某一事件情况只有两种,例如棋子翻转问题,除了黑就是白,那么我们就可以利用二进制来对事件的所有情况进行枚举。
通常我们设 1 为选取状态, 0 为未选取状态


先介绍位运算:
位运算是对二进制的每一位进行计算,所以每一位只有 0或 1两种可能

四种常用的位运算符:与&、或|、异或^, 按位取反~;

与运算:两者都为 1时,结果即为1,否则为0。--有0出0
或运算:两者都为 00时,结果即为0,否则为1。--有1出1
异或运算:是两者同为 0 或1 时,结果即为0,否则为1。相同出1 ,相异出0;
按位取反:将该二进制数上每一位取反,1变0,0变1

位运算的两种操作,左移<<和右移>>。

对于A << B,表示把A转化为二进制后向左移动B位(在末尾添加B个0, 即变成A乘以2的B次方)。

对于A >> B,表示把A转化为二进制后向右移动B位(删除末尾的B位, 即变成A除以2的B次方)。


我们来看一个可以用二进制枚举的方法解决的题目。

话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒两斗。他边走边唱:

无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。

这一路上,他一共遇到店 5 次,遇到花 10次,已知最后一次遇到的是花,他正好把酒喝光了。请你计算李白遇到店和花的次序,有多少种可能的方案。

这个题目解法很多,二进制枚举是一种写起来非常简洁的解法。我们已知遇店 5 次,遇花 10次,并且最后一次遇到花,正好把酒喝光。

这种情况我们可以直接跑暴力, 利用二进制枚举。

把店作为二进制中的 1,把花作为二进制中的 0,因为已经确定最后一次遇到的是花,所以我们需要判断枚举的结果是否刚好有 5个 1 和 9 个 0。那么我们就枚举出 14 位二进制的所有可能并加以判断即可。

/*
#include<bits/stdc++.h>
using namespace std;

int main(){
    int ans = 0;
    for(int i = 0; i < (1 << 14); i++){
        int num_0 = 0;
        int num_1 = 0;
        int num = 2;
        for(int j = 0 ; j < 14; j++){//从第0位到第13位;查看每一位是0还是1
            //j为0时,i&1-->查看的第一位;j为1时i&10-->查看第二位...以此类推
            if(i & (1 << j)){ // 这里判断二进制 i 从右数第 j + 1 位是否为 1
                num_1++;
                num*=2;
            }
            else{
                num_0++;
                num--;
            }
        }
        if(num_0 == 5 && num_1 == 9 && num == 1)
            ans++;// 记录合法方案数
    }
    printf("%d\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值