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\n", ++ Case,ans[n]);
	}
} 
posted @ 2020-09-05 20:06  王雨阳  阅读(121)  评论(0编辑  收藏  举报