GCD XOR UVA - 12716

问题

分析

这道题是我自己做不出来的
记录下思路
这道题肯定不能同时枚举a,b,否则肯定TLE,所以只枚举a,然后计算b。
思路:这涉及到gcd和xor之间的关系,设 a   x o r   b = c a\space xor\space b=c ,那么由异或的性质,可以得到 a   x o r   c = b a\space xor\space c=b 。所以可以枚举a和它的因数c作为gcd,然后计算出b,最后验证是否有 g c d ( a , b ) = c gcd(a,b)=c .这种做法的时间复杂度:枚举a和它的因数c是O(nlgn),然后gcd是O(lgn),所以总的是 O ( n ( l o g n ) 2 ) O(n(logn)^2)
继续优化,发现满足 g c d ( a , b ) = c = a   x o r   b gcd(a,b)=c=a\space xor\space b 的元素都满足a-b=c
证明:a-b<=a xor b且a-b>=c,c=gcd(a,b)=a xor b,所以a-b=c
所以,可以枚举a,c,计算b=a-c,验证b=a^c是否成立,时间时O(lgn)

#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=30000000+1;
int cnt[maxn],s[maxn];  //cnt:前缀,cnt[i],a=i时的情况数
int main(void){
    //类似埃氏筛的枚举方式
    for(int c=1;c<maxn;++c){  //枚举c
        for(int a=c*2;a<maxn;a+=c){  //枚举a
            if(a-c==(a^c)){
                cnt[a]++;
            }
        }
    }
    for(int i=1;i<maxn;++i) s[i]=s[i-1]+cnt[i];

    int T=0,kase=0,n=0;
    scanf("%d",&T);
    while(kase<T){
        scanf("%d",&n);
        printf("Case %d: %d\n",++kase,s[n]);
    }
    return 0;
}
发布了50 篇原创文章 · 获赞 0 · 访问量 678

猜你喜欢

转载自blog.csdn.net/zpf1998/article/details/104217942
今日推荐