题意:给你一个数N,问你在1-n的范围内有对少对数(x,y)保证gcd(x,y)=a xor y;
一开始看到的时候以为要拆位,想想觉得不对。然后把1-5之间的所有的对数列出来。。就会发现一个很好玩的性质:
如果 a xor b = gcd(a, b) = c 则 c = a - b
那不就变得很简单了吗,之间枚举a和c就可以了,结果比赛的时候傻逼了,没看见n<=10^7,因为直接上了gcd导致时间复杂度退化为O(NLOGN^2),被卡到60分。。醉了。。
代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
#define MOD 1000000007
#define mid(a,b)=a+b>>1
#define maxn 10000000
#define ll long long
ll n;
ll ans[maxn];
int main() {
int i,j;
scanf("%d",&n);
for (i=1;i<=n>>1;i++)
{
int u=i<<1;
while (u<=n)
{
int v=u-i;
if ((u^v)==i)
{
ans[u]++;
}
u+=i;
}
}
for (i=1;i<=n;i++)
ans[i]+=ans[i-1];
printf( "%lld\n",ans[n]) ;
return 0;
}