题面
分析
这种数据范围比较大的题最好的方法是先暴力打表找规律
通过打表,可以发现规律如下:
定义(x=2^{log_2a+1}) (注意,cf官方题解这里写错了,官方题解中定义(x=2^{log_2a})是有问题的
(1) 若(a eq 2^x-1)
则当(b=(2^x-1)) xor a时a xor b=b=(2^x-1) ,a and b=0
gcd(a xor b,a and b)=(2^x-1)有最大值
(异或的性质,若a xor c =b ,则a xor b=c)
举个例就很显然了:(注意,例子中数均用二进制表示)
a=101,2^x-1=111
b=101 xor 111 =010
a xor b =111
a and b =000
gcd(111,000)=111
(2) 若(a=2^x-1)
gcd(a xor b ,a and b)=(gcd(2^x-1-b,b))
由于(gcd(x,y)=gcd(x-y,y))
(gcd(2^x-1-b,b)=gcd(2^x-1,b))
所以我们只要找出(2^x-1)的最大且不为(2^x-1)的因数即可,可以直接试除法
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int divide(int x){
int sq=sqrt(x);
int ans=1;
for(int i=2;i<=sq;i++){
if(x%i==0){
ans=max(ans,i);
ans=max(ans,x/i);
}
}
return ans;
}
int count(int x){
int ans=0;
while(x>0){
x>>=1;
ans++;
}
return ans;
}
int solve(int x){
int l=count(x);
if((1<<l)-1==x) return divide(x);
else return (1<<l)-1;
}
int main(){
int q,x;
scanf("%d",&q);
while(q--){
scanf("%d",&x);
printf("%d
",solve(x));
}
}