Uva 12716

来源:互联网 发布:cordova项目app源码 编辑:程序博客网 时间:2024/06/06 10:53

题目链接

GCD XOR

题目分析

这个题是《刘汝佳算法经典》上面的题目,一个数域筛法的经典题目.我做一个搬运工~
一个基本的想法是枚举每个公约数c,a,由异或的特性我们有,a XOR b=c,b=a XOR c,,然后在判断一下是否满足gcd(a,b)==c,把答案加上.可以达到O(n(lgn)2),然而着中国做法会TLE.
如果你打印出几组结果出来看看,你可以发现,若gcd(a,b) = a^b=c,则必有c=ab,这样我们就只需要判断是否有a XOR b==c即可。O(nlgn)
证:
因为a XOR b=cab,gcd(a,b)=gcd(ab,b)=cab,所以c=ab

不过需要注意我们需要离线的计算出所有的解,因为T很大.

AC code

#include <cstdio>#include <iostream>#include <vector>#include <queue>#include <algorithm>#include<cmath>#include <cstring>#include <map>#define fi first#define se secondusing namespace std;const int MOD = 1e9+7;const int MAX_P = 2e4+10;const int maxn =3e7+10;typedef long long LL;LL gcd(LL a,LL b){  return b == 0? a : gcd(b,a%b);}int n;LL ans[maxn];LL sum[maxn];void init(){  memset(ans,0,sizeof(ans));  for(int c =1 ; c<maxn ; ++c){    for(int a = c*2 ; a<maxn ; a+=c){      int b = a-c;      if((a^b) == c)ans[max(a,b)]++;    }  }  sum[0] =0;  for(int i=1 ; i<maxn ; ++i)    sum[i]= sum[i-1]+ans[i];}int main(int argc, char const *argv[]) {  int T;  cin>>T;  int kase =0;  init();  while (T--) {    int n;    scanf("%d",&n );    printf("Case %d: %d\n",++kase,sum[n] );  }  return 0;}
0 0