[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]);
}
}