抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

题面

传送门:洛谷


Solution

一道很有意思的位运算题. 要做这一题,我们首先得了解一个很重要的特点 位运算过程中每一位都不会进位 有了这个特点,我们可以考虑一个很妙的做法 我们可以把每一扇门的那个数转为2进制 就可以在$O(n)$的时间内找到这一位以1或0为初始数,过完所有门后的这位数的结果 显然,结果为1是对答案有贡献的 然后,我们从后往前,一位一位枚举看一下初始值是填1还是填0 然后就OjbK了 时间复杂度$O(logm\cdot n)$


Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//Luogu P2114 [NOI2014]起床困难综合症
//May,26th,2018
//位运算拆分法
#include<iostream>
#include<cstdio>
using namespace std;
long long read()
{
long long x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=100000+1000;
const int LEN=35;
struct OP
{
int a[LEN],type;
}op[N];
long long n,m;
int Count(int x,int p)
{
for(int i=1;i<=n;i++)
{
if(op[i].type==1)
x=x & op[i].a[p];
else if(op[i].type==2)
x=x op[i].a[p];
else
x=x ^ op[i].a[p];
}
return x;
}
int main()
{
n=read(),m=read();
char temp[5];
for(int i=1;i<=n;i++)
{
scanf("%s",temp+1);
if(temp[1]=='A') op[i].type=1;
else if(temp[1]=='O') op[i].type=2;
else op[i].type=3;
int t_num=read();
for(int j=0;t_num!=0;j++)
{
op[i].a[j]=t_num%2;
t_num/=2;
}
}

long long used=0,ans=0;
for(int i=0;i<=30;i++)
{
int temp=Count(0,i);
if(temp==1)
{
ans+=(1<<i);
continue;
}
temp=Count(1,i);
if(temp==1 and used+(1<<i) <=m)
{
ans+=(1<<i);
used+=(1<<i);
}
}

printf("%lld",ans);
return 0;
}

评论