NOIP的板子们 (未完待续)

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP的板子们 (未完待续)相关的知识,希望对你有一定的参考价值。

1.数学

1.1、(扩展)欧几里得

void gcd(int a,int b,int &d,int &x,int &y)
{
    if(!b) { d=a; x=1; y=0; }
    else { gcd(b,a%b,d,y,x);  y-=x*(a/b); }
}
View Code

 

1.2、同余方程

//解同余方程 ax≡c(mod b)
//转化为ax-by=c 
void solve()
{
    gcd(a,b,g,x0,y0);  
    if(c%g) printf("no solution");
    x=c/g*x0; y=c/g*y0;
    printf("任意一组解:%d",x);
    a/=g; b/=g;
    x=(x%b+b)%b
    printf("最小x正整数解:%d",x); 
}
View Code

 

扩展欧几里得、同余方程 解析:http://www.cnblogs.com/TheRoadToTheGold/p/6645383.html

 

1.3、快速幂

int quickmul(int a,int b,int p)
{
    int ans=1;
    for(;b;b>>=1,a=a*a%p)
     if(b&1) ans=ans*a%p;
    return ans;
}  
View Code

 

1.4、素数判定

 

1.4.1. 费马小定理  若 a、p互质 ,则 a^(p-1) %p=1

缺陷:Carmichael数可以通过素数判定

O(次数*log)

#include<ctime>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long LL;
LL p;
bool flag;
LL mul(LL a,LL b)
{
    a%=p; b%=p;
    LL r=0;
    while(b)
    {
        if(b&1) { b--; r=(r+a)%p; }
        a<<=1; a%=p; b>>=1;
    }
    return r;
}
LL qm(LL a,LL b)
{
    LL r=1;
    while(b)
    {
        if(b&1) r=mul(r,a);
        b>>=1; a=mul(a,a);
    }
    return r;
}
int main()
{
    scanf("%lld",&p);
    srand(time(0));
    for(int i=1;i<=15;i++)
    {
        LL a=rand()%(p-1)+1;
        LL x=qm(a,p-1);
        if(x!=1) { flag=1; break; }
    }
    if(flag) printf("No");
    else printf("Yes");
}
View Code

 

1.4.2 Miller_Rabin

不会误判Carmichael数,误判概率为1/4^T

判断四五次大概够了

#include<ctime>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long LL;
LL p;
LL mul(LL a,LL b)
{
    LL r=0;
    while(b)
    {
        if(b&1) r+=a,r%=p;
        a<<=1; a%=p; b>>=1;
    }
    return r;
}
LL qm(LL a,LL b)
{
    LL r=1;
    while(b)
    {
        if(b&1) r=mul(r,a);
        a=mul(a,a);  b>>=1;
    }
    return r;
}
bool Miller_Rabin()
{
    if(p==2) return true;
    if(p==1 ||  p%2==0) return false;
    LL x,y,m,k=0,a;
    m=p-1;
    while(m%2==0) k++,m>>=1;
    int T=4;
    while(T--)
    {
        a=rand()%(p-1)+1;
        x=qm(a,m);
        for(int i=1;i<=k;i++)
        {
            y=mul(x,x);
            if(x&1 && y==1 && x!=1 && x!=p-1) return false;
            x=y;
        }
        if(x!=1) return false;
    }
    return true;
}
int main()
{
    srand(time(0));
    scanf("%lld",&p);
    if(Miller_Rabin()) printf("Yes");
    else printf("No");
}
View Code

 

1.5  素数相关

 

1.5.1 素数线性筛

void solve()
{
    for(int i=2;i<=N;i++)
    {
        if(!v[i])  prime[++cnt]=i;
        for(int j=1;j<=cnt;j++)
        {
            if(prime[j]*i>=N) break;
            v[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
}
View Code

 

1.5.2 唯一分解定理

#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
int p[100001],c[100001];
int main()
{
    int n,sum;
    while(scanf("%d",&n)!=EOF)
    {
        memset(c,0,sizeof(c));
        sum=0;
        int m=sqrt(n);
        for(int i=2;i<=m;i++)
         if(n%i==0)
         {
             p[++sum]=i;
             while(n%i==0) n/=i,c[sum]++;
         }
        if(n>1) p[++sum]=n,c[sum]++;
        for(int i=1;i<=sum;i++) printf("%d %d\\n",p[i],c[i]);
    }
}
View Code

 

1.5.3 阶乘的质因数分解

for(int i=1;prime[i]<=n;i++)
{
    int t=n;
    while(t)
    {
        cnt[i]+=t/prime[i];
        t/=prime[i];
    }
}
View Code

 

1.6 欧拉函数

原理 请转至http://www.cnblogs.com/TheRoadToTheGold/p/6598367.html

 

1.6.1  欧拉函数计算

void euler(int n)
{
    int ans=n;
    for(int i=2;i*i<=n;i++)
     if(n%i==0)
     {
         ans=ans/i*(i-1);
         while(n%i==0) n/=i;
     }
    if(n>1) ans=ans/n*(n-1);
}
View Code

 

 

1.6.2 欧拉筛

O(n)

void euler_table()
{
    phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!v[i]) 
        {
            prime[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=cnt;j++)
        {
            if(prime[j]*i>=N) break;
            v[prime[j]*i]=true;
            if(i%prime[j]) phi[prime[j]*i]=phi[i]*(prime[j]-1);
            else
            {
                phi[prime[j]*i]=prime[j]*phi[i];
                break;
            }
        }
    }
}
View Code

 

1.6.3 埃拉托斯特尼筛

O(nlog²n)

int eratosthenes(int n)
{
    int ans=n,k=n;
    int m=sqrt(n);
    for(int i=2;i<=m;i++)
     if(n%i==0)
     {
         ans=ans/i*(i-1);
         for(int j=1;j*i<=k;j++) v[i*j]=false;
         while(n%i==0) n/=i;
     }
    if(n>1)
    {
        ans=ans/n*i;
        for(int j=1;j*i<=k;j++) v[i*j]=false;
    }
    return ans;
}
View Code

 

1.6.4 杜教筛

待填坑

 

1.7 莫比乌斯函数

原理转至 http://www.cnblogs.com/TheRoadToTheGold/p/6598088.html

 

1.7.1 线性筛 

void mobius()
{
    mul[1]=1;
    for(int i=2;i<=n;i++) 
    {
        if(v[i]) 
        {
            prime[++cnt]=i;
            mul[i]=-1;
        }

        for(int j=1;j<=cnt;j++) 
        {
            if(i*prime[j]>=N) break;
            v[i*prime[j]]=true;
            if(i%prime[j]==0) { mul[i*prime[j]]=0; break; }
            mul[i*prime[j]]=-mul[i];
        }
    }
}
View Code

 

1.7.2 杜教筛

待填坑

 

1.8 逆元

只有 a p 互质,a才有关于p的逆元

原理请见:http://www.cnblogs.com/linyujun/p/5194184.html

 

1.8.1   费马小定理  限制条件:p是质数

int quickpow(int a,int b,int p)
{
    int r=1;
    while(b)
    {
        if(b&1) r8=a,r%=p;
        b>>=1; a*=a; a%=p;
    }
    return r;
}
void solve(int a,int p)
{
    if(prime(p)) printf("%d",quickpow(a,p-2,p));
}
View Code

 

1.8.2    扩展欧几里得

void exgcd(int a,int b,int& g,int& x,int& y)
{
    if(!b) { g=a; x=1; y=0; }
    else { exgcd(b,a%b,g,y,x); y-=x*(a/b); }
}
void solve()
{
    exgcd(a,b,g,x,y);
    if(g!=1) return;
    printf("%d",(x%p+p)%p);
}
View Code

 

1.8.3 递推 限制条件:p是质数

void solve(int p)
{
    inv[1]=1;
    for(int i=2;i<N;i++) inv[i]=(p-p/i)*inv[p%i]%p;
}
View Code

 

 

1.9 中国剩余定理

 

1.9.1 大数翻倍法

#include<cstdio>
using namespace std;
int n,a[11],b[11];
long long get_gcd(long long a,long long b)
{
    return !b ? a:get_gcd(b,a%b);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
    long long ans=b[1];
    long long lcm=a[1];
    for(int i=2;i<=n;i++)
    {
        while(ans%a[i]!=b[i]) ans+=lcm;
        long long gcd=get_gcd(lcm,(long long)a[i]);
        lcm=lcm/gcd*(long long)a[i];
    }
    printf("%lld",ans);
}
View Code

 

1.9.2 中国剩余定理 互质版

#include<cstdio>
using namespace std;
int n;
int m[11],a[11];
long long M=1,ans,Mi[11],e[11];
void exgcd(long long a,long long b,long long &x,long long &y)
{
    if(!b) x=1,y=0;
    else { exgcd(b,a%b,y,x); y-=x*(a/b); }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&m[i],&a[i]),M*=m[i];
    for(int i=1;i<=n;i++) Mi[i]=M/m[i];
    long long x,y;
    for(int i=1;i<=n;i++) 
    {
        exgcd(Mi[i],m[i],x,y);
        x=(x%m[i]+m[i])%m[i];
        e[i]=Mi[i]*x%M;
    }
    for(int i=1;i<=n;i++) ans=(ans+e[i]*a[i])%M;
    printf("%lld",ans);
}
View Code

 

这两个原理见:http://www.cnblogs.com/TheRoadToTheGold/p/6638430.html

  

1.9.3 中国剩余定理 非互质版

待填坑

 

1.10 卢卡斯定理

 

1.10.1 互质版

 

1.10.1.1  预处理阶乘

#include<cstdio>
using namespace std;
typedef long long LL;
LL f[100001];
void pre(int p)
{
    f[0]=1;
    for(int i=1;i<=p;i++) f[i]=f[i-1]*i%p;
}
int pow(LL a,int b,int p)
{
    LL r=1;
    while(b)
    {
        if(b&1) r*=a,r%=p;
        b>>=1; a*=a; a%=p; 
    }
    return r;
}
int C(int n,int m,int p)
{
    if(m>n) return 0; //如果m>n,那么原来的m<n-p,即m与n之间至少有一个p的倍数,那么结果为0 
    return f[n]*pow(f[m]*f[n-m],p-2,p)%p;
}
/*int Lucas(int n,int m,int p)
{
    if(!m) return 1;
    return (C(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
}*/
int Lucas(int n,int m,int p) //非递归版,上面是递归版 
{
    LL ans=1;
    for(;m;n/=p,m/=p) ans=ans*C(n%p,m%p,p)%p; 
    return ans;
}
int main()
{
    int T,n,m,p;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        pre(p);
        printf("%d\\n",Lucas(n,m,p));
    }    
}
View Code

 

1.10.1.2  阶乘不能预处理

#include<cstdio>
using namespace std;
typedef long long LL;
/*int pow(LL a,int b,int p)
{
    LL r=1;
    while(b)
    {
        if(b&1) r*=a,r%=p;
        b>>=1; a*=a; a%=p;
    }
    return r;
}*/
void exgcd(int a,int b,LL &x,LL &y)
{
    if(!b) { x=1; y=0; }
    else { exgcd(b,a%b,y,x); y-=x*(a/b); }
}
int inv(int x,int p)
{
    //return pow(x,p-2,p);
    LL x0,y0;
    exgcd(x,p,x0,y0);
    return (x0%p+p)%p;
}
int C(int n,int m,int p)
{
    if(n<m) return 0;
    LL r=1;
    //for(int i=m+1;i<=n;i++) r=r*i%p*inv(i-m,p)%p;  TLE
    for(int i=1;i<=m;i++) r=r*(n-i+1)%p*inv(i,p)%p;
    return r;
}
int Lucas(int n,int m,int p)
{
    LL ans=1;
    for(;m;n/=p,m/=p) 
    ans=ans*C(n%p,m%p,p)%p;
    return ans;
}
int main()
{
    int n,m,p;
    while(scanf("%d%d%d",&n,&m,&p)!=EOF)
    printf("%d\\n",Lucas(n,m,p));
}
View Code

 

 1.10.2  扩展卢卡斯

 待填坑

 

1.11 Catalan数

#include<cstdio>
#define mod 100000007
using namespace std;
long long f[20000];
int main()
{
    int n;
    scanf("%d",&n);
    f[0]=f[1]=1;
    for(int i=2;i<=n;i++)
     for(int j=1;j<=i;j++)
      f[i]=(f[i]+f[j-1]*f[i-j]%mod)%mod;
    //for(int i=2;i<=n;i++) f[i]=f[i-1]*(4*i-2)/(i+1);
    printf("%lld",f[n]);
}
View Code

 

1.12 矩阵树定理

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
long long t,C[101][101],ans;
long long Matrix_tree()
{
    ans=1;
    for(int i=1;i<n;i++)
    {
        for(int j=i+1;j<n;j++)
        while(C[j][i])
        {
            t=C[i][i]/C[j][i];
            for(int k=i;k<n;k++) C[i][k]-=C[j][k]*t;
            for(int k=i;k<n;k++) swap(C[i][k],C[j][k]);
            ans=-ans;
        }
        if(!C[i][i]) return 0;
        ans*=C[i][i];
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    int u,v;
    while(m--)
    {
        scanf("%d%d",&u,&v);
        u--; v--;
        C[u][v]--; C[v][u]--;
        C[u][u]++; C[v][v]++;
    }
    printf("%lld",Matrix_tree());
}
View Code

 

2.图论

2.1 最短路

 

2.1.1 Floyd 

  scanf("%d%d",&n,&m);
    memset(f,63,sizeof(f));
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        f[a][b]=f[b][a]=min(f[a][b],c);
    }
    for(int i=1;i<=n;i++) f[i][i]=0;
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
View Code

 

2.1.2 Dijkstra

 

2.1

以上是关于NOIP的板子们 (未完待续)的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2016 那些我所追求的 [未完待续]

2018.02.12 noip模拟赛T2(未完待续)

计算几何模板(未完待续)

设计模式总结对常用设计模式的一些思考(未完待续。。。)

模板区域[未完待续](会定期的更新哦(有时间就更了))

读caffe源码(未完待续)