声明
这并不是一篇讲述gcd与xor有什么神奇关系的文章,只是一道题目名而已。
题意
给定一个正整数n,在[1,n]的范围内,求出有多少个无序数对(a,b)满足gcd(a,b)=a xor b。
思考时间
…….
…….
…….
…….
…….
题解
我们来证明两个比较显然的命题,
对于两个正整数a,b且a大于b。
①a xor b
≥
a-b
②a-b
≥
gcd(a,b)
首先证明①:
根据xor的运算我们可以得到
∀p,q∈{0,1}
,有p xor q
≥
p-q
然后我们将a,b两个数转化为二进制,则有
a-b=
∑i=1(ai−bi)
,(
ai,bi∈{0,1}
)
a xor b=
∑i=1
(
ai
xor
bi
),(
ai,bi∈{0,1}
)
结合上面命题显然成立。
②:
设a=pd,b=qd,(p,q)=1,那么a,b的最大公约数即为d。
p-q=d(p-q),
若p=q,那么此时(p,q)=p,也即p和q的最大公约数不为1,矛盾,舍去。
若p大于q时,显然成立p-q=d(p-q)
>
d
进入正题
那么如果有a xor b=gcd(a,b),那么就有a xor b=a-b=gcd(a,b),也就是说gcd(a,b)=a-b。那么这样一来,题目就很简单了,我们可以类比线筛的方法,枚举一个a,b的gcd,然后再枚举一个a,算出b,判断一下是否有a xor b=c即可。
诡异的复杂度
1/n+2/n+……+n/n=nlogn,恕我学术不精,不会证。
代码:
const
maxn=1000000+5;
var
sum,ans:array[0..maxn] of longint;
i,j,k,a,b,c,t,n:longint;
begin
readln(t);
k:=1;
while t<>0 do
begin
dec(t);
readln(n);
if (sum[n]=0)and(k<=n) then
begin
for c:=k to n do
begin
a:=c*2;
while a<=maxn do
begin
b:=a-c;
if a xor b=c then
inc(ans[a]);
inc(a,c);
end;
end;
for i:=k to n do
begin
sum[i]:=sum[i-1]+ans[i];
end;
k:=n;
writeln(sum[n]);
end
else
writeln(sum[n]);
end;
end.
the end
由于我的水平有限,难免会有些写错的地方,希望大家批评指正,多多包容,thank you for your patience.