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\n",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\n",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;
    }
};

 

 

posted @ 2018-11-05 22:49  jiangminghong  阅读(275)  评论(0编辑  收藏  举报