[P2114] [NOI2014]起床困难综合症 (位运算)

题面

传送门:https://www.luogu.org/problemnew/show/P2114

 

 


 

Solution

一道很有意思的位运算题.

要做这一题,我们首先得了解一个很重要的特点

位运算过程中每一位都不会进位

 

有了这个特点,我们可以考虑一个很妙的做法

我们可以把每一扇门的那个数转为2进制

就可以在O(n) 的时间内找到这一位以1或0为初始数,过完所有门后的这位数的结果

显然,结果为1是对答案有贡献的

然后,我们从后往前,一位一位枚举看一下初始值是填1还是填0

然后就OjbK了

时间复杂度O(logm*n)

 


 

 Solution

//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;
}
正解(c++)

 

posted @ 2018-05-27 21:23  GoldenPotato  阅读(194)  评论(0编辑  收藏  举报