UVA12716 GCD等于XOR GCD XOR

[https://www.luogu.com.cn/problem/UVA12716]
sol:
异或的性质:
1.满足交换律,结合律
2.(a ^ a = 0)
3. 如果(a ^ b = c), 则 (b = c ^ a)

假设(gcd(a, b) = c), 那么(a ^ c = b),可以枚举(a)(c),计算(b),因为(c)(a)的约数,我们可以转化为枚举倍数,也就是枚举(c),类似于埃式筛法。因为需要计算(gcd)来验证,所以复杂度为
(O(nlog^2n)).打表发现,凡是符合题目要求的二元数,都满足(c = a - b).证明一下,因为(a xor b >= a - b), 并且(a - b >= c).这是因为(a = k c, b = tc, a - b = c(k-t)>= c).
所以(c = a xor b <= a - b <= a xor b).所以,(c = a - b.)

接下来,(gcd(a, b ) = gcd(a, a - c) = gcd(kc, (k - 1)c) = c * gcd(k, k - 1) = c)
我们发现,(gcd(a,b)) 的值就是(c),所以,我们就不用验证(gcd)了,只需要验证(a xor b) 是否等于就可以了。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 3e7 + 100;

int T, n, ans[N];

void solve() {
	for(int c = 1; c <= (N / 2); c ++) {
		for(int a = c + c; a <= N; a += c) {
			int b = a - c;
			if( (a ^ b) == c)
			    ans[a] ++;
		}
	}
	for(int i = 1; i <= N - 100; i ++)
	    ans[i] += ans[i - 1];
}

int main()
{
	scanf("%d", &T);
	solve();
	int Case = 0;
	while(T --) {
		scanf("%d", &n);
		printf("Case %d: %d
", ++ Case,ans[n]);
	}
} 
原文地址:https://www.cnblogs.com/wyy0804/p/13619498.html