异或
题目大意
问你不小于nnn的数对(a,b)(a,b)(a,b),有多少个满足gcd(a,b)=a⊕bgcd(a,b)=a \oplus bgcd(a,b)=a⊕b
输入样例#1
12
输出样例#1
8
输入样例#2
123456
输出样例#2
214394
数据范围
| 测试点 | 数据规模 | 
|---|---|
| 1 | 10 | 
| 2 | 100 | 
| 3 | 1000 | 
| 4 | 5000 | 
| 5 | 10000 | 
| 6 | 100000 | 
| 7 | 500000 | 
| 8 | 1000000 | 
| 9 | 5000000 | 
| 10 | 20000000 | 
解题思路
我们设c=gcd(a,b)c=gcd(a,b)c=gcd(a,b)
 我们可以枚举ccc
 然后枚举aaa是ccc的多少倍
 由此得出a,ca,ca,c
 我们可以通过gcdgcdgcd求出bbb然后判断是否满足a⊕b=ca \oplus b=ca⊕b=c
 但是这个时间复杂度过大,我们要进行优化
我们先证明a−b⩽a⊕ba-b \leqslant a \oplus ba−b⩽a⊕b
 我们观察以下两个字符串(x>y)(x>y)(x>y)
 x:x:x: 11001
 y:y:y: 00101
 xor:xor:xor: 11100
 1...对于x,yx,yx,y都是1的位xorxorxor和−-−得出结果都是0
2...对于只有yyy是1的位
 因为a>ba>ba>b,所以在更高的位肯定有只有xxx是1的位,这样减出来的结果才可能是正数
 因此−-−得出的结果是更高一位只有xxx是1的位减这一位
 而xorxorxor得出的是这两位的和
3...对于只有xxx是1且无需用去减的位xorxorxor和−-−得出结果都是1
 综上所述,a−b⩽a⊕ba-b \leqslant a \oplus ba−b⩽a⊕b
现在我们来证明c⩽a−bc \leqslant a-bc⩽a−b
 因为c=gcd(a,b)c=gcd(a,b)c=gcd(a,b)
 我们设
 a=c∗asa=c*asa=c∗as
 b=c∗bsb=c*bsb=c∗bs
若a=ba=ba=b则
 gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1
 a⊕b=0a \oplus b=0a⊕b=0
 gcd(a,b)≠a⊕bgcd(a,b) \neq a \oplus bgcd(a,b)=a⊕b
 ∴a≠b\therefore a \neq b∴a=b
∵a≠b且a⩾b\because a \neq b 且a \geqslant b∵a=b且a⩾b
 a>ba > ba>b
 ∵as>bs\because as > bs∵as>bs
 as−bs⩾1as - bs\geqslant 1as−bs⩾1
 (as−bs)×c⩾c(as - bs)\times c \geqslant c(as−bs)×c⩾c
 a−b⩾ca-b\geqslant ca−b⩾c
 若a−b≠ca-b\neq ca−b=c
 则c<a−b⩽a⊕bc < a-b \leqslant a \oplus bc<a−b⩽a⊕b
 c<a⊕bc<a \oplus bc<a⊕b
 无法满足c=a⊕bc=a \oplus bc=a⊕b
 ∴a−b=c\therefore a-b=c∴a−b=c
 这样我们通过b=a−cb=a-cb=a−c求出bbb
 然后判断ccc是否等于a⊕ba \oplus ba⊕b即可
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n, a, b, ans;
int main()
{scanf("%d", &n);for (int i = 1; i <= n / 2; ++i)for (int j = 2; i * j <= n; ++j){a = i * j;b = a - i;//求bif (i == (a^b)) ans++;}printf("%d", ans);return 0;
}