题目来源:CF1110C
【简要题意】给定a,求f(a)的最大值。
f
(
a
)
=
max
0
<
b
<
a
(
g
c
d
(
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))
【分析】
当
2
i
<
=
a
<
2
i
+
1
−
1
2^i<=a<2^{i+1}-1
2i<=a<2i+1−1时,
a
n
s
=
2
i
+
1
−
1
ans=2^{i+1}-1
ans=2i+1−1
否则,答案等于a除以除了1之外的最小因数。
具体证明也是分类讨论。当
2
i
<
=
a
<
2
i
+
1
−
1
2^i<=a<2^{i+1}-1
2i<=a<2i+1−1时,在a所有是0位上b全为1,其余全为0。显然会有
a
⊕
b
=
2
i
+
1
−
1
,
a
&
b
=
0
a\oplus b=2^{i+1}-1,a\ \& \ b=0
a⊕b=2i+1−1,a & b=0。由于b<a,所以一定不存在比它更大的数。
当
a
=
2
i
+
1
−
1
a=2^{i+1}-1
a=2i+1−1有一个特殊性质
a
⊕
b
+
a
&
b
=
a
a\oplus b+a\ \&\ b=a
a⊕b+a & b=a可以写成
f
(
a
)
=
max
0
<
d
<
=
a
2
(
g
c
d
(
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;
}