CF1491D(思维,位运算)
CF1491D(思维,位运算)
题意
一个无限大的有向图,按如下方式建边,问 \(u\) 是否可达 \(v\) 。
- 当 \(u\&v=v\) 时建立一条从 \(u\) 到 \(u+v\) 的边
思路
显然可达保证 \(u \le v\) 。
之后就没法一眼了,画图考虑一些特殊点。
画个图可以发现,\(2\) 的幂次只能走到二的幂次。进而我们想到,将建边方式看成一种移位方式,每次都可能将某位 \(1\) 左移一位或者不动。也就是形如 \(01 \rightarrow 10\) 的变化。
之后又发现,一些非 \(2\) 的整数幂也可以到 \(2\) 的幂次上,如 \(110 \rightarrow 1000\) 。我们发现对于多个一,我们总可以通过一些操作在左移的同时减少它们的个数。
因此我们得到结论,如果 \(u\) 从低到高 \(1\) 的个数总不少于 \(v\) 的个数,并且 \(u \le v\) 则一定可达。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<random>
#include<bitset>
#include<iomanip>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int u,v; cin >> u >> v;
bitset<32> bs1(u),bs2(v);
int cnt = 0;
rep(i,0,30) {
cnt += bs1[i] - bs2[i];
if(cnt < 0 || u > v) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
import sys
from math import *
input = sys.stdin.readline
def mrd(): return [int(x) for x in input().split()]
def rd(): return int(input())
MAXN = 2 * 10**5 + 5
INF = 10**16 * 2
mod = 10**9 + 7
#----------------------------------------------------------------------------------#
def solve():
u,v = mrd()
cnt = 0
for i in range(0,30):
cnt += (u >> i & 1) - (v >> i & 1)
if cnt < 0 or u > v:
print("NO")
return
print("YES")
if __name__ == "__main__":
for _ in range(rd()):
solve()