Codeforces 1110C (思维+数论)

题面

传送门

分析

这种数据范围比较大的题最好的方法是先暴力打表找规律

通过打表,可以发现规律如下:

定义\(x=2^{log_2a+1}\) (注意,cf官方题解这里写错了,官方题解中定义\(x=2^{log_2a}\)是有问题的

(1) 若\(a \neq 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\n",solve(x));
	}
}

posted @ 2019-02-08 21:15  birchtree  阅读(461)  评论(0)    收藏  举报