zoukankan      html  css  js  c++  java
  • UVA.12716 GCD XOR (暴力枚举 数论GCD)

    UVA.12716 GCD XOR (暴力枚举 数论GCD)

    题意分析

    题意比较简单,求[1,n]范围内的整数队a,b(a<=b)的个数,使得 gcd(a,b) = a XOR b.

    前置技能

    XOR的性质
    GCD

    由于题目只给出一个n,我们要求对数,能做的也始终暴力枚举a,b,这样就有n^2的复杂度,由于n很大,根本过不了。

    于是我们就想用到其中一些性质,如XOR 与GCD,不妨假设 a xor b = c,并且根据题意还知道, gcd(a,b) = c,也就说明c一定是a的因子,所以在枚举的时候,可以转过头来枚举a和c.那么如何求出当前情况下的b呢,考虑到xor的性质,即 a xor b = c, a xor c = a xor a xor b = b. 通过异或运算就可以求解出来b,然后再检验gcd(a,b)是否为c即可。

    到这里其实已经足够了,但是打出一定规模符合题意的(a,b,c),不难发现,a-b=c,有了这条性质,就可以不用gcd检验了。换句话说,通过枚举a,c,b = a-c计算出b,通过a^b=c检验是否符合条件。因为相对而言,位运算比gcd快得多。

    值得一提的是,由于n很大,连续处理多个n很大的值的时候,速度表现不能令人满意,最先想到的办法就是打表方法。

    代码总览

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define nmax 30000010
    #define ll long long
    using namespace std;
    int n;
    int t;
    int num[nmax];
    
    void init(){
        for(int c = 1;c<=(nmax+1)/2;++c){
            for(int a = c+c;a<nmax;a+=c){
                int b = a-c;
                if((a^b) == c) num[a]++;
            }
        }
        for(int i = 2;i<nmax;++i)  num[i]+=num[i-1];
    }
    
    int main()
    {
        int kase =1 ;
        init();
        scanf("%d",&t);
        for(kase  = 1; kase <=t;++kase){
            scanf("%d",&n);
            printf("Case %d: %d
    ",kase,num[n]);
        }
        return 0;
    }
  • 相关阅读:
    Netty源码分析之ByteBuf引用计数
    GitHub git push大文件失败(write error: Broken pipe)完美解决
    Windows10 Docker安装详细教程
    全面的Docker快速入门教程
    十本你不容错过的Docker入门到精通书籍推荐
    CentOS 8.4安装Docker
    postgres之一条sql查询总数及部分数据
    neo4j相关操作
    git上传大文件
    分布式文件系统fastdfs安装以及python调用
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367023.html
Copyright © 2011-2022 走看看