t(t<=1e4)组样例,每次给定a,b,d(1<=a,b,d<2的30次方)
求是否存在一个x(0<=x<2的60次方),满足(a|x)是d的倍数,且(b|x)是d的倍数,
其中|为二进制下的or,存在的话输出任意一个x即可,如果不存在,输出-1
官方题解&rainboy&inszva代码
先判断不合法的情形,
如果d为偶数,此时a和b如果有一个为奇数,则肯定无解,a%d必有余数
否则令d/2,a/2,b/2,继续判断,中途无解提前退出,...,直到d为奇数,
d为奇数后,一定有解,即任意数都有解,此时不妨令x=a|b,
为x构造出解之后,(a|x)=x,(b|x)=x,x也是原问题的解,
等价于解同余方程,
其中c为前面除以2的次数,两边同乘即可还原成原来的式子
先移项,然后由于d为奇数,,
可求2的逆元inv(2),实际上就是(d+1)/2,两侧同乘即可得到t,
,代入即可求得x
- #include
- using namespace std;
- typedef long long ll;
- int t,a,b,c,d,v;
- int main(){
- cin>>t;
- while(t--){
- cin>>a>>b>>d;
- c=0;
- while(a%2==0 && b%2==0 && d%2==0){
- a/=2,b/=2,d/=2;
- c++;
- }
- if(d%2==0){
- cout<<-1<
- continue;
- }
- int inv=(d+1)/2;
- v=1;
- for(int i=0;i<30-c;++i){
- v=1ll*v*inv%d;
- }
- int r=((d-(a|b))%d+d)%d;
- ll x=1ll*v*r%d;
- a<<=c;b<<=c;
- cout<<((x<<30)|(a|b))<
- }
- return 0;
- }
代码2(inszva代码)
先判完不合法的情形
注意到d是一个奇数,所以可以起到对某一位赋1的作用,
从低位到高位考虑最后30位,低位已经为1了,高位的相加就不会影响低位
每次加上的都是d的倍数,最终答案一定是d的倍数,
这样还能保证二进制最后30位全是1
- #include
- using namespace std;
- typedef long long ll;
- int t;
- ll a,b,d,v;
- int main(){
- cin>>t;
- while(t--){
- cin>>a>>b>>d;
- int c=0;
- while(a%2==0 && b%2==0 && d%2==0){
- a/=2,b/=2,d/=2;
- c++;
- }
- if(d%2==0){
- cout<<-1<
- continue;
- }
- ll x=0;
- for(int i=0;i<30;++i){
- int bit=x>>i&1;
- if(!bit){
- x+=d<//d奇数 必能使第i位为1
- }
- }
- cout<<(x<
- }
- return 0;
- }
-
相关阅读:
七、Kafka-Kraft 模式
甲骨文、SUSE 和 CIQ (Rocky Linux )提供Open Enterprise Linux Association (OpenELA)
Rt-Thread 4-线程
QTday4
MySQL——数据库基础
还在每天玩单调的控制台窗口?赶紧进来!!!用EasyX画出自己的优美窗口(万字教程,一文入门)
Qt实现一个简易截图工具(支持缩放、移动、保存、复制到粘贴板)
std::bind 源码分析
CLR via C#-托管堆和垃圾回收
【Notepad】Notepad++ 安装XML/Json插件,格式化xml/json文件
-
原文地址:https://blog.csdn.net/Code92007/article/details/127835565