Zookeeper and The Infinite Zoo(CF1491D)(位运算)

题意:
题目给出 \(q\) 个询问,问有向图上 \(u\) 是否可以到达 \(v\),其中图上的边 \(u\rightarrow (u+v)\) 存在的条件是 \(u\&v=v\)


想法:

  • 考虑条件 \(u\&v=v\) 如何才能成立,发现只要对于二进制位上的 \(1\)\(v\) 有的 \(u\) 都有即可。
  • \(u\) 到达 \(v\),就是通过一些加法,让两个数相等即可。
  • \(u>v\),显然不可达。
  • \(u=v\),显然可达。
  • \(u<v\),对于两个二进制串,我们发现一定可以通过符合条件的加法让低位上的 \(1\) 变到高位上的 \(1\),并且二进制中 \(1\) 的数量只能变少不能变多,综上,也就得出一个结论:计算 \(u\)\(v\) 的二进制中 \(1\) 的个数,做一个前缀和,对于每一位必须$ v1[i]>=v2[i]$ 能保证 \(u\)\(v\)

代码:

int v1[50],v2[50];
int main()
{
    int q,u,v;
    cin>>q;
    while(q--){
        mem(v1,0);
        mem(v2,0);
        scanf("%d%d",&u,&v);
        if(u>v){
            puts("NO");
        }else{
            for(int i=0;i<=30;i++){
                if((u>>i)&(1)){
                    v1[i]=1;
                }
            }
            for(int i=0;i<=30;i++){
                if((v>>i)&(1)){
                    v2[i]=1;
                }
            }
            for(int i=1;i<=30;i++){
                v1[i]+=v1[i-1];
                v2[i]+=v2[i-1];
            }
            int k=1;
            for(int i=0;i<=30;i++){
                if(v2[i]>v1[i]){
                    k=0;
                    break;
                }
            }
            if(k){
                puts("YES");
            }else{
                puts("NO");
            }
        }
    }
}
posted @ 2021-03-01 15:03  hachuochuo  阅读(171)  评论(0编辑  收藏  举报