zoukankan      html  css  js  c++  java
  • NOIP的基本模板合集(1)

    目录:

    1.线性推逆元

    2.线性筛素数

    3.线性筛欧拉函数

    4.质因数分解

    5.gcd及exgcd

    6.快速幂及快速乘

    7.LCA算法(最近公共祖先)

    8.树状数组

    9.卢卡斯定理

    10.高精度(加、减、压位乘法)

    一.线性推逆元

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    long long n,p,inv[3000001];
    int main()
    {
        scanf("%lld%lld",&n,&p);
        inv[1]=1;
        for(long long i=2;i<=n;i++)
            inv[i]=(p-p/i)*inv[p%i]%p;
    }

    二.线性筛素数

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    int n,prime[100001],idx;
    bool notprime[100001];
    int main()
    {
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            if(notprime[i]==0)
            {
                prime[++idx]=i;
            }
            for(int j=1;j<=idx&&i*prime[j]<=n;j++)
            {
                notprime[i*prime[j]]=1;
                if(i%prime[j]==0)
                    break;
            }
        }
    }

    三.线性筛欧拉函数

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    int n,prime[100001],idx,phi[100001];
    bool notprime[100001];
    int main()
    {
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            if(notprime[i]==0)
            {
                prime[++idx]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=idx&&i*prime[j]<=n;j++)
            {
                notprime[i*prime[j]]=1;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                else
                    phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }

     四.质因数分解

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    int n,a[10001],idx;
    int main()
    {
        scanf("%d",&n);
        for(int i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                a[++idx]=i;
                while(n%i==0)
                    n/=i;
            }
            if(n!=1)
                a[++idx]=n;
        }
        return 0;
    }

    五.gcd及exgcd

    1.gcd

    int gcd(int x,int y)
    {
        if(y==0)
            return x;
        return gcd(y,x%y);
    }

    2.exgcd

    int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return a;
        }
        int cnt=exgcd(b,a%b,x,y);
        int idx=x;
        x=y;
        y=idx-a/b*y;
        return cnt;
    }

    六.快速幂及快速乘

    1.快速幂

    int pow(int x,int y)
    {
        int ans=1;
        while(y)
        {
            if(y&1)
                ans=(ans*x)%mod;
            x=(x*x)%mod;
            y>>=1;
        }
    }

    2.快速乘

    int mul(int x,int y)
    {
        int ans=0;
        while(y)
        {
            if(y&1)
                ans=(ans+x)%mod;
            x=(x+x)%mod;
            y>>=1;
        }
    }

    七.LCA算法(最近公公祖先)

    1.树链剖分求LCA

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    #define N 500001
    int n,m,s,to[N<<1],head[N],idx,nxt[N<<1],top[N],son[N],dep[N],siz[N],f[N];
    void addedge(int x,int y)
    {
        to[++idx]=y;
        nxt[idx]=head[x];
        head[x]=idx;
    }
    void dfs1(int x)
    {
        dep[x]=dep[f[x]]+1;
        siz[x]=1;
        for(int i=head[x];i;i=nxt[i])
            if(f[to[i]]==0&&to[i]!=f[x])
            {
                f[to[i]]=x;
                dfs1(to[i]);
                siz[x]+=siz[to[i]];
                if(siz[son[x]]<siz[to[i]])
                    son[x]=to[i];
            }
    }
    void dfs2(int x)
    {
        if(x==son[f[x]])
            top[x]=top[f[x]];
        else
            top[x]=x;
        for(int i=head[x];i;i=nxt[i])
            if(to[i]!=f[x])
                dfs2(to[i]);
    }
    int lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
                y=f[top[y]];
            else
                x=f[top[x]];
        }
        if(dep[x]>dep[y])
            return y;
        else
            return x;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        dfs1(s);
        dfs2(s);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
    }

     八.树状数组

    1.单点加(单点修改)

    int c[N];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,int del)
    {
        while(x<=n)
        {
            c[x]+=del;
            x+=lowbit(x);
        }
    }

    2.单点查询

    int c[N];
    int lowbit(int x)
    {
        return x&(-x);
    }
    int query(int x)
    {
        int ans=0;
        while(x)
        {
            ans+=c[x];
            x-=lowbit(x);
        }
        return ans;
    }

     九.卢卡斯定理(以洛谷模板为例)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    #define N 100001
    int n,m,t,p;
    long long fac[N];
    long long mul(long long x,long long y,long long mod)
    {
        long long ans=0;
        while(y)
        {
            if(y&1)
                ans=(ans+x)%mod;
            x=(x+x)%mod;
            y>>=1;
        }
        return ans;
    }
    long long pow(long long x,long long y,long long mod)
    {
        long long ans=1;
        while(y)
        {
            if(y&1)
                ans=mul(ans,x,mod)%mod;
            x=mul(x,x,mod)%mod;
            y>>=1;
        }
        return ans;
    }
    long long C(long long x,long long y,long long mod)
    {
        if(y<x)
            return 0;
        if(x==y)
            return 1;
        return mul(mul(fac[y],pow(fac[x],mod-2,mod),mod),pow(fac[y-x],mod-2,mod),mod);
    }
    long long Lucas(long long x,long long y,long long mod)
    {
        if(x==0)
            return 1;
        return mul(Lucas(x/mod,y/mod,mod),C(x%mod,y%mod,mod),mod);
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&p);
            fac[1]=1;
            for(int i=2;i<=p;i++)
                fac[i]=mul(fac[i-1],i,p);
            printf("%lld
    ",Lucas(m,n+m,p));
        }
    }

     十.高精度(感谢ysy20021208提供模板)

    高精加、减、压位乘法(重载运算符版)

    #define mod 100000000
    struct Num
    {
        long long num[N];
        Num() {memset(num,0,sizeof(num));}
        Num operator + (const Num &a) const
        {
            Num ans;ans.num[0]=max(a.num[0],num[0]);long long tmp=0;
            for(int i=1;i<=ans.num[0];i++)
                ans.num[i]=num[i]+a.num[i]+tmp,tmp=ans.num[i]/mod,ans.num[i]%=mod;
            while(tmp) ans.num[++num[0]]=tmp%mod,tmp/=mod;
            return ans;
        }
        Num operator - (const Num &a) const
        {
            Num ans;ans.num[0]=num[0];long long tmp=0;
            for(int i=1;i<=ans.num[0];i++)
            {
                if(num[i]-tmp-a.num[i]<0) ans.num[i]=num[i]-tmp-a.num[i]+mod,tmp=1;
                else ans.num[i]=num[i]-tmp-a.num[i],tmp=0;
            }
            while(ans.num[ans.num[0]]==0) ans.num[0]--;
            return ans;
        }
        Num operator * (const Num &a) const
        {
            Num ans,tmp;long long tmp1=0,tmp2;
            for(int i=1;i<=a.num[0];i++)
            {
                tmp2=a.num[i],tmp.num[0]=i-1,tmp1=0,tmp.num[tmp.num[0]]=0;
                for(int j=1;j<=num[0];j++)
                {
                    tmp.num[++tmp.num[0]]=num[j]*tmp2+tmp1;
                    tmp1=tmp.num[tmp.num[0]]/mod,tmp.num[tmp.num[0]]%=mod;
                }
                while(tmp1) tmp.num[++tmp.num[0]]=tmp1%mod,tmp1/=mod;
                ans=ans+tmp;return ans;
            }
        }
        Num operator ^ (const int &a) const
        {
            Num ans,x;int y=a;ans.num[0]=ans.num[1]=1;
            for(int i=0;i<=num[0];i++) x.num[i]=num[i];
            while(y) {if(y&1) ans=ans*x;x=x*x,y>>=1;} return ans;
        }
    };

     

  • 相关阅读:
    【BZOJ 3754】: Tree之最小方差树
    【cogs 775】山海经 ——Segment Tree
    【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】
    【BZOJ 2004】: [Hnoi2010]Bus 公交线路
    开启22端口
    将MySQL数据库表结构,自动生成PDM方法
    linux环境 创建多版本php
    mysql 数据类型选择浅谈
    int(5) 到底是多长
    (记)小程序如何发布
  • 原文地址:https://www.cnblogs.com/jiangminghong/p/9912158.html
Copyright © 2011-2022 走看看