紫书 例题 10-5 UVa 12716 (枚举方式)

设gcd(a, b) = a xor b = c

那么我们可以证明c=a-b

那么同时c又是a的因子(c是a与b的最大公因数)

所以我们可以枚举c,然后枚举c的倍数,也就是a

有了a和c可以算出b为a-c

然后最后验算是否a xor b = c就ok了。

这里的枚举方式非常的巧妙,是反过来枚举c

来推a,如果枚举a的因子c的话就会很耗时间了。

#include<cstdio>
#include<cmath>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;

const int MAXN = 30000001;
int cnt[MAXN], sum[MAXN];

void init()
{
	REP(c, 1, MAXN)
		for(int a = c * 2; a < MAXN; a += c)
			if(c == (a ^ (a - c))) cnt[a]++;
	REP(i, 1, MAXN) sum[i] = sum[i-1] + cnt[i];
}

int main()
{
	init();
	int T, kase = 0, n;
	scanf("%d", &T);
	
	while(T--)
	{
		scanf("%d", &n);
		printf("Case %d: %d
", ++kase, sum[n]);
	}
	
	return 0;
}

原文地址:https://www.cnblogs.com/sugewud/p/9819514.html