- 题意:
- 给定N,求二元组(A,B)的个数,满足:
- 1<=A<=B<=NAxorB==gcd(A,B)
规模:
- 1≤N≤30000000
- T≤10000
类型:
- 数论,gcd
分析:
- 这里有一个规律:
- 如果AxorB==gcd(A,B),则A-B==gcd(A,B)
证明:
- 1式:AxorB>=A−B
- 这里考虑将AB对应位数字不同的位置,交换使得,1在A里,0在B里,
- 这样变化后异或值不变,但A-B增大。极限情况下AxorB==A−B
- 2式:gcd(A,B)<=A−B ( 这个易证 )
- 而我们有 AxorB==gcd(A,B),由12两式AxorB==(A−B)==gcd(A,B)
- 1式:AxorB>=A−B
接下来,枚举gcd(A,B)(设为C)的值,A是C的倍数,看B是否符合
- B==AxorC ==A-C
- 代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF=0x3fff3fff;
const int MAXN=3e7+10;
const int MAXM=40010;
const int MOD=10001;
typedef long long ll;
long long n,m;
//long long x[2100];
int aa[MAXN];
int ans[MAXN];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int T,n,a,b,c;
memset(ans,0,sizeof(ans));
memset(aa,0,sizeof(ans));
for(int i=1;i<MAXN;i++){
// cout<<i<<endl;
for(int j=2;j*i<MAXN;j++){
c=i;a=i*j;
b=c^a;//b=a-c
if(b==a-c){aa[a]++;}
}
}
for(int i=2;i<MAXN;i++){
ans[i]=ans[i-1]+aa[i];
//cout<<aa[i]<<",";
}
cin>>T;
int kase=0;
while(T--){
cin>>n;
printf("Case %d: %d\n", ++kase, ans[n]);
}
return 0;
}