zoukankan      html  css  js  c++  java
  • 数论算法模板(不定期更新)

    /**********/
    
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<vector>
    #include<stack>
    #include<map>
    using namespace std;
    typedef long long ll;
    
    /***********GCD**********************/
    
    ll gcd(ll a,ll b)
    {
        if(b==0)
            return a;
        return gcd(b,a%b);
    }
    
    /*************快速乘***************/
    
    ll mult_mod(ll a,ll b,ll mod)
    {
        a%=mod; b%=mod;
        ll res=0;
        while(b)
        {
            if(b&1)
            {
                res+=a;
                res%=mod;
            }
            a<<=1;
            if(a>=mod) a%=mod;
            b>>=1;
        }
        return res;
    }
    
    /*************快速幂**************/
    
    ll pow_mod(ll x,ll n,ll mod)
    {
        if(n==1) return x%mod;
        x%=mod;
        ll t=x,res=1;
        while(n)
        {
            if(n&1) res=mult_mod(res,t,mod);
            t=mult_mod(t,t,mod);
            n>>=1;
        }
        return res;
    }
    
    /*****更快的*****快速幂***************/
    
    ll pow_mod(ll x,ll n,ll mod)
    {
        ll res=1;
        ll tmp=x%mod;
        while(n)
        {
            if(n&1)
            {
                res*=t;
                res%=mod;
            }
            n>>=1;
            t*=t;
            t%=mod;
        }
        return res;
    }
    
    /************扩展欧几里德****************/
    
    void extend_gcd(ll a,ll b,ll &x,ll &y)
    {
        ll d; //d=gcd(a,b)
        if(b==0)
        {
            x=1,y=0;
            d=a;
        }
        else
        {
            d=extend_gcd(b,a%b,y,x);
            ll xx=x,yy=y;
            x=yy;
            y=xx-(a/b)*yy;
        }
    }
    
    /************素数筛法******************/
    
    ll l,u,prime[N];
    int tot;
    int vis[N],ans[10000005];
    
    void isPrime()
    {
        tot=0;
        memset(vis,0,sizeof(vis));
        memset(prime,0,sizeof(prime));
        for(ll i=2;i<N;i++)
        {
            if(!vis[i])
            {
                prime[tot++]=i;
                for(ll j=i*i;j<N;j+=i)
                    vis[j]=1;
            }
        }
    }
    
    /******更快的*素数筛选*******************/
    
    const int MAXN=10000;
    int prime[MAXN+1];
    void isPrime()
    {
        memset(prime,0,sizeof(prime));
        //素数存储从下标1开始,prime[0]记录素数个数
        for(int i=2;i<=MAXN;i++)
        {
            if(!prime[i])
                prime[++prime[0]]=i;
            for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++)
            {
                prime[prime[j]*i]=1;
                if(i%prime[j]==0)
                    break;
            }
        }
    }
    
    /*********素数判定Miller_Rabin***********/
    
    bool test(ll a,ll n) //Miller_Rabin算法的核心
    {
        ll x=n-1,t=0,res,last;
        while((x&1)==0)
        {
            x>>=1;
            t++;
        }
        last=pow_mod(a,x,n);
    
        for(int i=0;i<t;i++)
        {
            res=pow_mod(last,2,n);
            if(res==1&&last!=1&&last!=n-1)
                return true;
            last=res;
        }
        if(res!=1) return true;
        return false;
    }
    
    bool millier_rabin(ll n)
    {
        if(n==2) return true;
        if(n==1||(n&1)==0) return false;
        for(int i=0;i<times;i++)
        {
            ll a=rand()%(n-1)+1;
            if(test(a,n))
                return false;
        }
        return true;
    }
    
    /*******质因数分解********************/
    
    ll factor[100][2];
    int cnt;
    //分解质因数:A=(p1^a1)*(p2^a2)*...*(pn^an)
    //factor[i][0]=pi,factor[i][1]=ai;
    void getFactor(ll x)
    {
        cnt=0;
        ll t=x;
        for(int i=0;prime[i]<=t/prime[i];i++)
        {
            factor[cnt][1]=0;
            while(t%prime[i]==0)
            {
                factor[cnt][0]=prime[i];
                while(t%prime[i]==0)
                {
                    factor[cnt][1]++;
                    t/=prime[i];
                }
                cnt++;
            }
        }
        if(t!=1)
        {
            factor[cnt][0]=t;
            factor[cnt][1]=1;
            cnt++;
        }
    }
    
    /*********大数因数分解Pollard_rho*************/
    
    ll pollard_rho(ll x,ll c)
    {
        ll x0,y,i=1,k=2;
        x0=rand()%x;
        y=x0;
        while(1)
        {
            i++;
            x0=(mult_mod(x0,x0,x)+c)%x;
            ll d=gcd(y-x0,x);
            if(d>1&&d<x) return d;
            if(y==x0) break;
            if(i==k)
            {
                y=x0;
                k+=k;
            }
        }
        return x;
    }
    
    void find_fac(ll n,int c)
    {
        if(n==1) return;
        if(millier_rabin(n))
        {
            factor[tot++]=n;
            return;
        }
        ll p=n;
        while(p>=n)
            p=pollard_rho(p,c--);
        find_fac(p,c);
        find_fac(n/p,c);
    }
    
    /**********正约数和(二分求法)**************/
    
    //将A进行因式分解可得:A = p1^a1 * p2^a2 * p3^a3 * pn^an
    //A^B=p1^(a1*B)*p2^(a2*B)*...*pn^(an*B);
    //A^B的所有约数之和sum=[1+p1+p1^2+...+p1^(a1*B)]*[1+p2+p2^2+...+p2^(a2*B)]*[1+pn+pn^2+...+pn^(an*B)].
    //等比数列1+pi+pi^2+pi^3+...+pi^n可以由二分求得(即将需要求解的因式分成部分来求解)
    //若n为奇数,一共有偶数项,则
    //1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2))*(1+p^(n/2+1));
    //若n为偶数,一共有奇数项,则
    //1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2-1))*(1+p^(n/2+1))+p^n/2;
    
    ll sum(ll p,ll n)
    {
        if(p==0) return 0;
        if(n==0) return 1;
        if(n&1)
            return ((1+pow_mod(p,n/2+1))%MOD*sum(p,n/2)%MOD)%MOD;
        else
            return ((1+pow_mod(p,n/2+1))%MOD*sum(p,n/2-1)+pow_mod(p,n/2)%MOD)%MOD;
    }
    
    /**********欧拉函数**********************/
    
    int Euler(int n)
    {
        int res=n;
        for(int i=2;i*i<=n;i++)
        {
            while(n%i==0)
            {
                n/=i; res-=(res/i);
                while(n%i==0)
                    n/=i;
            }
        }
        if(n>1)
           res-=(res/n);
        return res;
    }
    
    /******素数筛法+欧拉打表**********/
    
    ll e[N+5],p[N+5];
    bool vis[N+5];
    
    void init()
    {
        memset(e,0,sizeof(e));
        memset(p,0,sizeof(p));
        memset(vis,false,sizeof(vis));
        ll i,j;
        p[0]=1;//记录素数总个数
        p[1]=2;
    
        for(i=3;i<N;i+=2)
        {
            if(!vis[i])
            {
                p[++p[0]]=i;
                for(j=i*i;j<N;j+=i)
                    vis[j]=true;
            }
        }
    
        e[1]=1;
        for(i=1;i<=p[0];i++)
            e[p[i]]=p[i]-1; //为什么要-1?
    
        for(i=2;i<N;i++)
        {
            if(!e[i])
            {
                for(j=1;j<=p[0];j++)
                {
                    if(i%p[j]==0)
                    {
                        if(i/p[j]%p[j])
                            e[i]=e[i/p[j]]*e[p[j]];
                        else
                            e[i]=e[i/p[j]]*p[j];
                        break;
                    }
                }
            }
        }
    }
    
    /*************欧拉打表*更快版***************/
    
    #define N 1000000
    
    int e[N+5];
    void init()
    {
        int i,j;
        memset(e,0,sizeof(e));
        for(i=2;i<=N;i++)
        {
            if(!e[i])
            {
                for(j=i;j<=N;j+=i)
                {
                    if(!e[j])
                        e[j]=j;
                    e[j]=e[j]/i*(i-1);
                }
            }
        }
    }
    
    /**********容斥原理*二进制解法**************/
    
    vector<int> v;
    ll solve(int l,int r,int n) //[l,r]内与n互素的数字个数
    {
        v.clear();
        //筛选素数
        for(int i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                v.push_back(i);
                while(n%i==0)
                    n/=i;
            }
        }
        if(n>1)
            v.push_back(n);
    
        //容斥原理的二进制解法
        int len=v.size();
        ll res=0;
        for(int i=1;i<(1<<len);i++)
        {
            int cnt=0;
            ll val=1;
            for(int j=0;j<len;j++)
            {
                if(i&(1<<j))
                {
                    cnt++;
                    val*=v[j];
                }
            }
            if(cnt&1) //若为奇数项进行加法,偶数项进行减法
                res+=r/val-(l-1)/val;
            else res-=r/val-(l-1)/val;
        }
        return r-l+1-res;
    }
  • 相关阅读:
    通用页面调用APP 互通
    HTML5[5]:在移动端禁用长按选中文本功能
    JAVA 中的基础
    手机访问PC网站自动跳转到手机网站代码
    自适应的设置字体的方式
    localStorage 与 sessionStorage
    《高级程序设计》3 基本慨念
    javascript基础
    jQuery技巧
    jQuery性能优化
  • 原文地址:https://www.cnblogs.com/atmacmer/p/5285810.html
Copyright © 2011-2022 走看看