起床困难综合征

题意: 给定 n n n个操作和数 m m m,问当初值在 [ 1 , m ] [1,m] [1,m]时,按照 n n n个操作的顺序操作后可以获得的最大值。
数据范围: 1 ≤ n ≤ 1 0 5 , 1 ≤ m ≤ 1 0 9 1\leq n\leq 10^5, 1\leq m\leq 10^9 1n105,1m109,操作只有或运算,与运算和异或运算三种。

题解:
位运算每位独立,故可以单独考虑每位。

  • 由于二进制每位只有两种取值,故可以考虑每位初值为0和1的情况。那么对应的十进制初值只需要用两个数: a 0 = 0 a_0=0 a0=0和不小于 m m m的梅森数 a 1 a_1 a1即可,对应二进制位即全 0 0 0和全 1 1 1
  • 在对 a 0 a_0 a0 a 1 a_1 a1进行 n n n组操作后,记操作后的数为 s 0 s_0 s0 s 1 s_1 s1
  • 优先处理二进制高位,保证答案最大。同时在取可以为 1 1 1的位时,优先取由 a 0 a_0 a0转移过来的。当考虑 a 1 a_1 a1转移过来的位时,保证此时的位十进制大小加上之前的大小和不大于 m m m

代码:

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

int main()
{
	int n, m; 
	scanf("%d%d", &n, &m);
	int a0 = 0, a1 = -1;
	for(int i = 1; i <= n; ++i) {
		char op[10]; int x;
		scanf("%s%d", op, &x); 
		if(*op == 'A') a0 &= x, a1 &= x;
		else if(*op == 'X') a0 ^= x, a1 ^= x;
		else a0 |= x, a1 |= x;
	}
	
	int sum = 0;
	for(int i = 1 << 29; i >= 1; i >>= 1) {
		if(a0 & i) sum |= i;
		else if((a1 & i) && i <= m) sum |= i, m -= i; 
	} 
	
	printf("%d\n", sum);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值