题目来源:CF1110C
【简要题意】给定a,求f(a)的最大值。f(a)=max0<b<a(gcd(a⊕b,a & b))f(a)= \max\limits_{0<b<a}(gcd(a\oplus b,a\ \&\ b))f(a)=0<b<amax(gcd(a⊕b,a & b))
【分析】
当2i<=a<2i+1−12^i<=a<2^{i+1}-12i<=a<2i+1−1时,ans=2i+1−1ans=2^{i+1}-1ans=2i+1−1
否则,答案等于a除以除了1之外的最小因数。
具体证明也是分类讨论。当2i<=a<2i+1−12^i<=a<2^{i+1}-12i<=a<2i+1−1时,在a所有是0位上b全为1,其余全为0。显然会有a⊕b=2i+1−1,a & b=0a\oplus b=2^{i+1}-1,a\ \& \ b=0a⊕b=2i+1−1,a & b=0。由于b<a,所以一定不存在比它更大的数。
当a=2i+1−1a=2^{i+1}-1a=2i+1−1有一个特殊性质a⊕b+a & b=aa\oplus b+a\ \&\ b=aa⊕b+a & b=a可以写成f(a)=max0<d<=a2(gcd(a−d,d))f(a)= \max\limits_{0<d<=\frac{a}{2}}(gcd(a-d,d))f(a)=0<d<=2amax(gcd(a−d,d))相当于把a分成几份取其中的最大公因数。
【code】
x没有每次打初始化结果只有十分。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
bool check(int x){
while(x>0)
if(x&1)x>>=1;
else return 0;
return 1;
}
int solve(int x){
for(int i=2;i*i<=x;i++)
if(x%i==0)return x/i;
return 1;
}
int main(){
freopen("meaning.in","r",stdin);
freopen("meaning.out","w",stdout);
int T,n,x;
cin>>T;
while(T--){
cin>>n;
if(check(n)) printf("%d\n",solve(n));
else{
while(x<n)x=(x<<1)+1;
printf("%d\n",x);
}
}
return 0;
}