位运算c++

一.位运算简介:


任何信息在计算机中都是采用二进制表示的,数据在计算机中是以补码形式存储的,位运算就是直接对整数在内存中的二进制进行运算。由于位运算直接对内存数据进行操作,不需要直接转换成十进制,因此,处理速度非常快,在信息学竞赛中往往可以优化理论时间复杂度的系数。
c++提供了按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)、右移(>>)这6种运算符。

1.按位与(&)

a a a & b b b ”是指将参与运算的两个整数用二进制进行“与”的操作,如果值都为一就输出1,否则为0

2.按位或(|)

a a a | b b b ”是指将参与或运算的两个整数用二进制进行“或”的操作,如果值有一个为一就为1,如果两个都是0,那就是0

3.按位异或(^)

a a a ^ b b b ”是指将参与异或的两个整数用二进制进行“异或”的操作,如果值不一样为1,否则位0

4.取反(~)

“ ~ a a a ”是指将参与取反的一个整数用二进制进行“取反”的操作,把a的二进制值反过来,为1取反完就为0,为0取反完就为1

5.左移(<<)

a a a << b b b ”是指将参与左移的两个数用二进制进行“左移”的操作,把 a a a 的二进制值向左移动 b b b

6.右移(>>)

a a a >> b b b ”是指将参与右移的两个数用二进制进行“右移”的操作,把 a a a 的二进制值向右移动 b b b

二.位运算的应用


例题一:枚举子集

题目描述

给定 n n n 个元素,输出 n n n 个元素构成的集合的所有子集。简化:以 n n n 个连续的 0/1 代表第 i i i 个元素是否选中(0:未选中,1:选中)。

输入格式

一行,一个正整数 n ( n < 20 ) n(n<20) n(n<20)

输出格式

输出共 2 n 2^n 2n 行,每行一个 0/1 构成的字符串,表示子集。
按字典序输出。

样例 #1

样例输入 #1

4

样例输出 #1

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

这道题要用到左移( i i i & ( 1 (1 (1 << j ) j) j)来解题

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<(1<<n);i++)
	{
		for(int j=n-1;j>=0;j--)		//这里要从小到大(从0001)开始判断
		{
			if(i&(1<<j))	//判断i个元素是否选中
			{
				cout<<1;	//是就输出1
			}
			else
			{
				cout<<0;	//不是输出0
			}
		}
		cout<<'\n';		//不能用endl,因为endl比‘\n’慢100毫秒,在此题中会超时(TLE)
	}
	return 0;
}

例题二:小书童——刷题大军

题目描述

小A“刷题”十分猖狂,明目张胆地“刷题”。他现在在小书童里发现了n样他喜欢的“题目”,每“题”都有他的需要时间,而老师布置了 m m m 项作业,每项作业都有它的需要时间及分值,老师规定 k k k 分以上(包括 k k k 分)算及格。小A只剩 r r r 个单位时间,他想在及格的基础上更多地“刷题”。

输入格式

第一行: n , m , k , r n,m,k,r n,m,k,r 。第二行: n n n 个数,代表每“题”他的需要时间。第三行: m m m 个数。表示每项作业它的需要时间。第四行: m m m 个数。代表每项作业它的分值。

输出格式

一个数,代表小A能刷几道题

样例 #1

样例输入 #1

3 4 20 100
15 20 50
10 15 40 40
5 5 10 15

样例输出 #1

2

提示

没有不能及格的情况
对于 100 100 100% 的数据,
n ≤ 10 , m ≤ 10 , k ≤ 50 , r ≤ 150 n≤10,m≤10,k≤50,r≤150 n10,m10,k50,r150

这道题要先做完作业后用最小的时间做最多的题

#include<bits/stdc++.h>
using namespace std;
int n,m,k,r,t[100],c[100],v[100],ans=1e9;	//ans的值要定义的足够大
int main()
{
	cin>>n>>m>>k>>r;
	for(int i=1;i<=n;i++)
	{
		cin>>t[i];	//代表每“题”他的需要时间
	}
	for(int i=1;i<=m;i++)
	{
		cin>>c[i];	//表示每项作业它的需要时间
	}
	for(int i=1;i<=m;i++)
	{
		cin>>v[i];	//代表每项作业它的分值
	}
	for(int i=0;i<(1<<m);i++){
		int sum=0, time=0;
		for(int j=0;j<m;j++){
			if(i&(1<<j)){	//判断
				sum += v[j+1];
				time += c[j+1];
			}
		}
		if(sum>=k && time<=r){
			ans = min(ans, time);	//在时间里找最小值
		}
	}
	r-=ans;
	sort(t+1,t+n+1);
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(r>=t[i]){
			cnt++;		//找出最多能做几道题
			r -= t[i];
		}else{
			break;
		}
	} 	
	cout<<cnt<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值