GCD和XOR

来源:互联网 发布:linux apache2.0下载 编辑:程序博客网 时间:2024/06/10 02:16

声明

这并不是一篇讲述gcd与xor有什么神奇关系的文章,只是一道题目名而已。

题意

给定一个正整数n,在[1,n]的范围内,求出有多少个无序数对(a,b)满足gcd(a,b)=a xor b。

思考时间

…….
…….
…….
…….
…….

题解

我们来证明两个比较显然的命题,
对于两个正整数a,b且a大于b。
①a xor ba-b
②a-b gcd(a,b)
首先证明①:
根据xor的运算我们可以得到p,q{0,1},有p xor qp-q
然后我们将a,b两个数转化为二进制,则有
a-b=i=1(aibi),(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.

原创粉丝点击