Codeforces Round #833 (Div. 2) D. ConstructOR

题目链接

题意:

T T T 组样例,每次输入三个数 a , b , d a,b,d a,b,d 问能否找到一个数 x x x 使得 a ∣ x a|x ax d d d 的倍数且 b ∣ x b|x bx d d d 的倍数,若存在解则输出任意一个,不存在输出 -1

范围:
0 ≤ x < 2 60 0≤x<2^{60} 0x<260 , 1 ≤ a , b , d < 2 30 1≤a,b,d<2^{30} 1a,b,d<230 , T ≤ 1 e 4 T≤1e4 T1e4

思路:

我们用 c c [ q q ] cc[qq] cc[qq] 代表 q q qq qq 的二进制的最低位的1是哪一位
首先我们容易发现,若 c c [ a ] < c c [ d ] ∣ c c [ b ] < c c [ d ] cc[a]<cc[d] | cc[b]<cc[d] cc[a]<cc[d]cc[b]<cc[d] 则一定无解,因为 d d d 的所有可能的倍数的二进制的最低位1一定不会低于 c c [ d ] cc[d] cc[d]

剩下 c c [ a ] > = c c [ d ] cc[a]>=cc[d] cc[a]>=cc[d]&& c c [ b ] > = c c [ d ] cc[b]>=cc[d] cc[b]>=cc[d] 这种情况
要直接求 a ∣ x a|x ax b b b 的倍数且 b ∣ x b|x bx d d d 的倍数显然较难,考虑到 x x x 的范围很大,不妨构造出这样一个 x x x x ∣ a = x ∣ b = x x|a=x|b=x xa=xb=x x x x d d d 的倍数

d d d 为奇数
只需要将 x x x [ 0 , 30 ) [0,30) [0,30) 位全都赋为1,且使得 x x x d d d 的倍数
可以从低位往高位递推 ( i = 0 ; i < 30 ; i + + ) (i=0;i<30;i++) (i=0;i<30;i++) ,每次判断 x x x 的第 i i i 为是否为0,若为0则加一个 d < < i d<<i d<<i ,因为 d d d 为奇数所以一定可以使得 x x x 的第 i i i 位变为1(将 d d d 的第0位1移过来),同时对低位不造成影响

d d d 为偶数
因为 c c [ d ] < = c c [ a ] cc[d]<=cc[a] cc[d]<=cc[a]&& c c [ d ] < = c c [ b ] cc[d]<=cc[b] cc[d]<=cc[b] ,所以可以先考虑 [ c c [ d ] , 30 ) [cc[d],30) [cc[d],30) 这些位,那么 d d d 仍然可以看做一个奇数,与上面同样做法,最后还原一下即可

代码:

//cc&qq
#include <bits/stdc++.h>
#define  ll long long
using namespace std;
const ll mod=1e9+7;
const int N=2e6+10; 
ll a,b,c,d,qa,qb,qc,qd;
int main()
{
	ll t,i,n,g,j,m,k,h,l,r,mid,max1,min1,p,i1,j1,v,x0,y0,x1,y1,x,y,r1,r2;
	
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld%lld",&a,&b,&d);x=0;c=0;
		for(i=0;i<=31;i++)if((1<<i)&a){qa=i;break;}
		for(i=0;i<=31;i++)if((1<<i)&b){qb=i;break;}
		for(i=0;i<=31;i++)if((1<<i)&d){qd=i;break;}
		if(min(qa,qb)<qd){printf("-1\n");continue;}
		
		for(i=qd;i<30;i++){
			if(!((1<<(i-qd))&x))x+=((d/(1<<qd))<<(i-qd));
		}
		printf("%lld\n",x*(1<<qd));
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值