【数学】异或

探讨了在特定条件下,如何寻找满足gcd(a,b)=a⊕b的数对(a,b)的数量,通过对异或运算性质的深入分析,提出了一种有效的算法解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异或

题目大意

问你不小于nnn的数对(a,b)(a,b)(a,b),有多少个满足gcd(a,b)=a⊕bgcd(a,b)=a \oplus bgcd(a,b)=ab

输入样例#1

12

输出样例#1

8

输入样例#2

123456

输出样例#2

214394

数据范围

测试点数据规模
110
2100
31000
45000
510000
6100000
7500000
81000000
95000000
1020000000

解题思路

我们设c=gcd(a,b)c=gcd(a,b)c=gcd(a,b)
我们可以枚举ccc
然后枚举aaaccc的多少倍
由此得出a,ca,ca,c
我们可以通过gcdgcdgcd求出bbb然后判断是否满足a⊕b=ca \oplus b=cab=c
但是这个时间复杂度过大,我们要进行优化


我们先证明a−b⩽a⊕ba-b \leqslant a \oplus babab
我们观察以下两个字符串(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 babab


现在我们来证明c⩽a−bc \leqslant a-bcab
因为c=gcd(a,b)c=gcd(a,b)c=gcd(a,b)
我们设
a=c∗asa=c*asa=cas
b=c∗bsb=c*bsb=cbs

a=ba=ba=b
gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1
a⊕b=0a \oplus b=0ab=0
gcd(a,b)≠a⊕bgcd(a,b) \neq a \oplus bgcd(a,b)=ab
∴a≠b\therefore a \neq ba=b

∵a≠b且a⩾b\because a \neq b 且a \geqslant ba=bab
a>ba > ba>b
∵as>bs\because as > bsas>bs
as−bs⩾1as - bs\geqslant 1asbs1
(as−bs)×c⩾c(as - bs)\times c \geqslant c(asbs)×cc
a−b⩾ca-b\geqslant cabc
a−b≠ca-b\neq cab=c
c<a−b⩽a⊕bc < a-b \leqslant a \oplus bc<abab
c<a⊕bc<a \oplus bc<ab
无法满足c=a⊕bc=a \oplus bc=ab
∴a−b=c\therefore a-b=cab=c
这样我们通过b=a−cb=a-cb=ac求出bbb
然后判断ccc是否等于a⊕ba \oplus bab即可

代码

#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;//求b
			if (i == (a^b)) ans++;
		}
	printf("%d", ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值