数学模板

· · 算法·理论

这是一篇关于数学模板的文章 这些是其他模板分类的链接 数据结构 字符串 杂项 图论

高精度计算


# 快速幂
- [P1226 【模板】快速幂||取余运算](https://www.luogu.com.cn/problem/P1226)
```cpp
int power(long long a, int b, int p){
    long long s=1;
    for(int i=b; i; i>>=1){
        if(i&1) s=s*a%p;
        a=a*a%p;
    }
    return s;
}

应用

模意义下大整数乘法

快速乘


# 数论
## 最大公约数
- [B3634 最大公约数和最小公倍数](https://www.luogu.com.cn/problem/B3634)
```cpp
int gcd(int x, int y){
    for(int i=x%y; i; i=x%y) x=y, y=i;
    return y;
}

最小公倍数


## 欧拉函数
- [Laoj P1468 [模板]欧拉函数](http://luanoj.cn:9090/oj/Problem_Show.asp?id=1468)
```cpp
int euler(int x){
    int s=x;
    for(int i=2; i*i<=x; i++){
        if(!(x%i)){
            s=s/i*(i-1);
            while(!(x%i)) x/=i;
        }
    }
    if(x>1) s=s/x*(x-1);
    return s;
}

筛法

素数筛法

void sieve(int n){ int c=0; bitset<N> u;

for(int i=2; i<=n; i++){
    if(!u[i]) p[++c]=i;

    for(int j=1; j<=c && i*p[j]<=n; j++){
        u[i*p[j]]=1;
        if(!(i%p[j])) break;
    }
}

}


#### 非前缀区间素数筛法
- [P1835 素数密度](https://www.luogu.com.cn/problem/P1835)
```cpp
int p[P];

void sieve(int l, int r){
    int c=0;
    bitset<N> u;

    for(int i=2; (long long)i*i<=r; i++){
        if(!u[i]) p[++c]=i;

        for(int j=1; j<=c && i*p[j]<=sqrt(r); j++){
            u[i*p[j]]=1;
            if(!(i%p[j])) break;
        }
    }

    u.reset();
    for(int i=1; i<=c; i++){
        for(int j=max(2,(l-1)/p[i]+1); j<=r/p[i]; j++) u[j*p[i]-l]=1;
    }
}

筛法求欧拉函数

void sieve(int n){ int c=0; bitset<N> u;

e[1]=1;
for(int i=2; i<=n; i++){
    if(!u[i]) p[++c]=i, e[i]=i-1;

    for(int j=1; j<=c && i*p[j]<=n; j++){
        u[i*p[j]]=1;
        if(i%p[j]) e[i*p[j]]=e[i]*e[p[j]];
        else{
            e[i*p[j]]=e[i]*p[j];
            break;
        }
    }
}

}


## 乘法逆元
### 扩展欧几里得法
- [P1082 [NOIP2012 提高组] 同余方程](https://www.luogu.com.cn/problem/P1082)
```cpp
long long x,y;

long long exgcd(int a, int b){
    if(!b){
        x=1, y=0;
        return a;
    }

    long long r=exgcd(b,a%b), t=x;
    x=y, y=t-a/b*y;
    return r;
}

int inv(int a, int p){
    return exgcd((a%p+p)%p,p)==1 ? (x%p+p)%p : -1;
}

线性求逆元

int main(){ int n,p; scanf("%d%d",&n,&p);

inv[1]=1;
for(int i=2; i<=n; i++) inv[i]=(p-p/i)*inv[p%i]%p;

}


## 线性同余方程
- [Laoj P1467 [模板]线性同余方程](http://luanoj.cn:9090/oj/Problem_Show.asp?id=1467)
```cpp
int sol(int a, int b, int p){
    if(!a) return b%p ? -1 : 0;

    int d=exgcd(a,p);
    if(b%d) return -1;

    b/=d, p/=d;
    return (x*b%p+p)%p;
}

中国剩余定理

long long crt(){ long long p=1; for(int i=1; i<=n; i++) p*=m[i];

long long s=0;
for(int i=1; i<=n; i++){
    long long t=p/m[i];
    s=(s+a[i]*t%p*inv(t,m[i])%p)%p;
}
return s;

}


### 扩展:模数不互质的情况
- [P4777 【模板】扩展中国剩余定理(EXCRT)](https://www.luogu.com.cn/problem/P4777)
```cpp
long long a[N],m[N];

long long excrt(){
    for(int i=2; i<=n; i++){
        if(a[1]>a[i]) swap(a[1],a[i]), swap(m[1],m[i]);

        long long d=gcd(m[1],m[i]), p=lcm(m[1],m[i]);
        if((a[i]-a[1])%d) return -1;

        exgcd(m[1]/d,m[i]/d);
        a[1]=(a[1]+mul(mul((a[i]-a[1])/d,(x%p+p)%p,p),m[1],p)%p+p)%p, m[1]=p;
    }
    return a[1];
}

卢卡斯定理

int lucas(int n, int m, int p){ return n<m ? 0 : n ? com(n%p,m%p,p)*lucas(n/p,m/p,p)%p : 1; }


### 扩展卢卡斯定理
- [P4720 【模板】扩展卢卡斯定理/exLucas](https://www.luogu.com.cn/problem/P4720)
```cpp
long long a[L],m[L];

long long fac(long long n, long long p, long long pk){
    if(!n) return 1;

    long long s=1;
    for(int i=1; i<pk; i++){
        if(i%p) s=s*i%pk;
    }
    s=power(s,n/pk,pk);

    for(int i=1; i<=n%pk; i++){
        if(i%p) s=s*i%pk;
    }
    return s*fac(n/p,p,pk)%pk;
}

long long com(long long n, long long m, long long p, long long pk){
    if(n<m) return 0;

    long long s=0, t1=fac(n,p,pk), t2=fac(m,p,pk), t3=fac(n-m,p,pk);
    for(long long i=n; i; i/=p) s+=i/p;
    for(long long i=m; i; i/=p) s-=i/p;
    for(long long i=n-m; i; i/=p) s-=i/p;
    return t1*inv(t2,pk)%pk*inv(t3,pk)%pk*power(p,s,pk)%pk;
}

long long exlucas(long long n, long long m, long long p){
    int c=0;
    for(int i=2; i*i<=p; i++){
        long long t=1;
        while(!(p%i)) p/=i, t*=i;
        if(t>1) a[++c]=com(n,m,i,t), ::m[c]=t;
    }
    if(p>1) a[++c]=com(n,m,p,p), ::m[c]=p;
    return crt(c);
}

离散对数


# 线性代数
## 矩阵
- [B2105 矩阵乘法](https://www.luogu.com.cn/problem/B2105)
- [P3390 【模板】矩阵快速幂](https://www.luogu.com.cn/problem/P3390)
```cpp
struct mat{
    int n,m;
    long long a[N][N];

    mat(){
        n=m=0, memset(a,0,sizeof a);
    }

    mat(int x, int y){
        n=x, m=y, memset(a,0,sizeof a);
    }

    void read(){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=m; j++) scanf("%lld",&a[i][j]);
        }
    }

    mat operator *(mat x){
        mat y={n,x.m};
        for(int i=1; i<=n; i++){
            for(int j=1; j<=x.m; j++){
                for(int k=1; k<=m; k++) y.a[i][j]=(y.a[i][j]+a[i][k]*x.a[k][j])%MOD;
            }
        }
        return y;
    }

    mat pow(long long x){
        mat s={n,n}, a=*this;
        for(int i=1; i<=n; i++) s.a[i][i]=1;

        for(long long i=x; i; i>>=1){
            if(i&1) s=s*a;
            a=a*a;
        }
        return s;
    }

    void print(){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=m; j++) printf("%lld ",a[i][j]);
            putchar('\n');
        }
    }
};

高斯消元

struct mat{ bool cmp(int p, int x, int y){ if(fabs(fabs(a[x][p])-fabs(a[y][p]))>EPS) return fabs(a[x][p])>fabs(a[y][p]); for(int i=p+1; i<=n; i++){ if(fabs(fabs(a[x][i])-fabs(a[y][i]))>EPS) return fabs(a[x][i])<fabs(a[y][i]); } return 0; }

int gauss(){
    for(int i=1; i<=n; i++){
        int t=i;
        for(int j=i+1; j<=n; j++){
            if(cmp(i,j,t)) t=j;
        }
        if(t!=i) swap(a[t],a[i]);
        if(fabs(a[i][i])<EPS) continue;

        for(int j=m; j>=i; j--) a[i][j]/=a[i][i];
        a[i][i]=1;
        for(int j=i+1; j<=n; j++){
            for(int k=m; k>=i; k--) a[j][k]-=a[i][k]*a[j][i];
        }
    }

    for(int i=n; i; i--){
        if(fabs(a[i][i])<EPS) continue;
        for(int j=1; j<i; j++) a[j][m]-=a[j][i]*a[i][m], a[j][i]=0;
    }

    int f=1;
    for(int i=1; i<=n; i++){
        if(fabs(a[i][i])<EPS){
            if(a[i][m]>EPS) return -1;
            else f=0;
        }
    }
    return f;
}

};