【数学】异或

异或

题目大意

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

输入样例#1

12

输出样例#1

8

输入样例#2

123456

输出样例#2

214394

数据范围

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

解题思路

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


我们先证明 a − b ⩽ a ⊕ b a-b \leqslant a \oplus b abab
我们观察以下两个字符串 ( x > y ) (x>y) x>y
x : x: x: 11001
y : y: y: 00101
x o r : xor: xor: 11100
1 . . .对于 x , y x,y x,y都是1的位 x o r xor xor − - 得出结果都是0

2 . . .对于只有 y y y是1的位
因为 a > b a>b a>b,所以在更高的位肯定有只有 x x x是1的位,这样减出来的结果才可能是正数
因此 − - 得出的结果是更高一位只有 x x x是1的位减这一位
x o r xor xor得出的是这两位的和

3 . . .对于只有 x x x是1且无需用去减的位 x o r xor xor − - 得出结果都是1
综上所述, a − b ⩽ a ⊕ b a-b \leqslant a \oplus b abab


现在我们来证明 c ⩽ a − b c \leqslant a-b cab
因为 c = g c d ( a , b ) c=gcd(a,b) c=gcd(a,b)
我们设
a = c ∗ a s a=c*as a=cas
b = c ∗ b s b=c*bs b=cbs

a = b a=b a=b
g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1
a ⊕ b = 0 a \oplus b=0 ab=0
g c d ( a , b ) ≠ a ⊕ b gcd(a,b) \neq a \oplus b gcd(a,b)=ab
∴ a ≠ b \therefore a \neq b a=b

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

代码

#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、付费专栏及课程。

余额充值