注意到a^b>=a-b>=gcd(a,b)【前一条考虑0^0=0-0,1^1=1-1,0^1>0-1,1^0=1-0,后一条根据辗转相减法】。因此在枚举a和c之后,取b=a-c,则必有gcd(a,b)=gcd(a,a-c)=c,只需要验证b=a^c即可。时间复杂度O(nlogn)。
【代码】
//UVa 12716 GCD XOR
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=3*1e7;
int n;
int c[mxn+5];
int main()
{
int i,j,x;
fo(i,1,mxn)
for(j=2*i;j<=mxn;j+=i)
if((i^j)==(j-i)) c[j]++;
fo(i,1,mxn) c[i]+=c[i-1];
scanf("%d",&n);
fo(i,1,n)
{
scanf("%d",&x);
printf("Case %d: %lld\n",i,c[x]);
}
return 0;
}