zoukankan      html  css  js  c++  java
  • GCD + 素数+快速幂

    1.欧几里得算法

    求解最大公约数,时间复杂度在O(log max(a,b))以内,可以看出,辗转相除法是非常高效的

    int gcd(int a,int b)
    {
        return (b==0)?a:gcd(b,a%b);
    }

    2.扩展欧几里得算法

    求解方程a*x+b*y=gcd(a,b),a、b、x、y均为整数,时间复杂度和辗转相除法是相同的,函数返回gcd(a,b)。

    int gcd(int a,int b)
    {
        return (b==0)?a:gcd(b,a%b);
    }
    int extgcd(int a,int b,int& x,int& y)
    {
        int d=a;
        if(b!=0){
            d=extgcd(b,a%b,y,x);
            y-=(a/b)*x;
        }
        else{
            x=1;
            y=0;
        }
        return d;
    }

    3.素数测试

    //素性测试O(√n)
    bool is_prime(int n)
    {
        for(int i=2;i*i<=n;i++){
            if(n%i==0) return false;
        }
        return n!=1;//n等于1是例外
    }
    //约数枚举O(√n)
    vector<int> divisor(int n)
    {
        vector<int> res;
        for(int i=2;i*i<=n;i++){
            if(n%i==0){
                res.push_back(i);
                if(i!=n/i) res.push_back(n/i);
            }
        }
        return res;
    }
    //整数分解O(√n)素数因子
    map<int,int> prime_factor(int n)
    {
        map<int,int> res;
        for(int i=2;i*i<=n;i++){
            while(n%i==0){
                ++res[i];
                n/=i;
            }
        }
        if(n!=1) res[n]=1;
        return res;
    }

    其中map第一个int是n的素数因子,对应的第二个int是这个因子的个数

    2.埃式筛法

    给定一个正整数n,请问n以内有多少个素数。

    首先将2到n的所有整数记下来,其中最小的整数2是素数,将表中2的倍数划去。表中最小的整数是3,它不能被更小的数整除,所以是素数,将表中3的倍数划去,以此类推,表中剩余的最小数字是m,则m就是素数。这样反复操作即可枚举得到n以内的所有素数,时间复杂度为O(nloglogn),可以看作是线性时间。

    int prime[maxn];
    bool is_prime[maxn];//is_prime[i]是true表示i是素数
    //返回n以内素数的个数
    int sieve(int n)
    {
        int p=0;
        for(int i=0;i<=n;i++) is_prime[i]=true;
        is_prime[0]=is_prime[1]=false;
        for(int i=2;i<=n;i++){
            if(is_prime[i]){
                prime[p++]=i;
                for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
            }
        }
        return p;
    }

    3.区间筛法

    给定整数a、b,求区间[a,b)内有多少个素数

    b以内的合数的最小质因数一定不超过√b。如果有√b以内的素数表,就可以把埃式筛法用到区间[a,b)上了。也就是说,先做好[2,√b)和[a,b)的表,然后从[2,√b)表中筛选素数的同时,也将其倍数从[a,b)的表中划去,最后剩下的就是[a,b)内的素数了。

    typedef long long ll;
    bool is_prime[1000000+5];
    bool is_prime_small[1000000+5];
    //对区间[a,b)内的整数执行筛法。is_prime[i-a]=true→i是素数
    void segment_sieve(ll a,ll b)
    {
        for(int i=0;(ll)i*i<b;i++) is_prime_small[i]=true;
        for(int i=0;i<b-a;i++) is_prime[i]=true;
        for(int i=2;(ll)i*i<b;i++){
            if(is_prime_small[i]){
                for(int j=2*i;(ll)j*j<b;j+=i) is_prime_small[i]=false;//筛[2,√b)
                for(ll j=max(2ll,(a+i-1)/i)*i;j<b;j+=i) is_prime[j-a]=false;//筛[a,b)
                //2LL是2的长整数形式
                //((a+i-1)/i)*i是满足>=a&&%i==0的离a最近的数
                //也可以写成(a%i==0)?a:(a/i+1)*i
            }
        }
    }

    4.快速幂运算

    typedef long long ll;
    ll mod_pow(ll x,ll n,ll mod)
    {
        ll res=1;
        while(n>0){
            if(n&1) res=res*x%mod;
            x=x*x%mod;
            n>>=1;
        }
        return res;
    }
  • 相关阅读:
    IO多路复用 IO异步
    你没听说过的协程
    事件驱动和IO操作
    堡垒机前戏——paramiko
    听说过的多进程,多线程到底是什么鬼
    socket套接字
    看见就烦的异常
    struts2值栈内部数据结构详解
    hibernate一级缓存的源码初窥
    使用自定义标签模拟jstl的<c:for each>标签
  • 原文地址:https://www.cnblogs.com/zllwxm123/p/9542621.html
Copyright © 2011-2022 走看看