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");
}
}
}
}
越自律,越自由