题意:
T T T 组样例,每次输入三个数 a , b , d a,b,d a,b,d 问能否找到一个数 x x x 使得 a ∣ x a|x a∣x 是 d d d 的倍数且 b ∣ x b|x b∣x 是 d d d 的倍数,若存在解则输出任意一个,不存在输出 -1
范围:
0
≤
x
<
2
60
0≤x<2^{60}
0≤x<260 ,
1
≤
a
,
b
,
d
<
2
30
1≤a,b,d<2^{30}
1≤a,b,d<230 ,
T
≤
1
e
4
T≤1e4
T≤1e4
思路:
我们用
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
a∣x 为
b
b
b 的倍数且
b
∣
x
b|x
b∣x 为
d
d
d 的倍数显然较难,考虑到
x
x
x 的范围很大,不妨构造出这样一个
x
x
x ,
x
∣
a
=
x
∣
b
=
x
x|a=x|b=x
x∣a=x∣b=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));
}
}