数学专题总结

来源:互联网 发布:1064 mysql 编辑:程序博客网 时间:2024/05/21 12:01

数学专题总结

  • 扩展欧几里得算法
    扩展欧几里得算法就是用来求解不定方程ax+by=gcd(a,b)的一组特解的算法,它相比普通的欧几里得算法不仅能求出两个数之间的最大公约数,还能顺便解方程,相比普通的欧几里得算法要强一些.

代码如下:

void exgcd(int a,int b,int &x,int &y,int &d){    if(!b){d=a; x=1; y=0; return;}    exgcd(b,a%b,y,x,d);    y-=(a/b)*x;}
  • 欧拉筛法筛素数
    欧拉筛法相比普通的线性筛是要快一些的,它快的地方主要是每个素数只访问一次,能减少重复的次数,代码比起线性筛要稍微长那么一些.

代码如下

void make_prime(int n){    npr[0]=1;npr[1]=1;    for(int i=2;i<=n;i++){        if(!npr[i])pr[++cnt]=i;          for(int j=1;j<=cnt&&pr[j]*i<=n;j++){              npr[pr[j]*i]=1;             //欧拉函数的积性            if(i%pr[j]==0)break;          }      }}
  • 欧拉函数
    欧拉函数是用来求在1-n中与n互质的数的个数的函数.函数具体为:
    φ(n)=n(11p1)(11p2)...(11pk)
    其中p1-pk都表示n的质因数.
    并且欧拉函数是积性函数,即φ(ab)=φ(a)φ(b)(a,b)=1

代码如下:

void phi_table(int n){    phi[1]=1;    for(int i=2;i<=n;i++){        if(!phi[i]){            for(int j=i;j<=n;j+=i){                if(!phi[j])phi[j]=j;                phi[j]=phi[j]/i*(i-1);            }        }    }}
  • 逆元
    这里的逆元我主要指的是模意义下的逆元.如果ax1(modp),我们就称a对于p的逆元为x,记作a1,可以形象地认为它就是aa在模意义下的倒数.求逆元可以用扩展欧几里得算法,不过我重点要介绍一种线性求逆元的方法.即在线性的时间内求出1-p-1的所有逆元,且p为质数.

我们可以设p=ki+rp=ki+r
那么显然有ki+r\equiv 0(mod\quad p)ki+r0(modp)
我们两边同时乘上一个{ i }^{ -1 }{ r }^{ -1 }i1r1
那么就有k{ r }^{ -1 }+{ i }^{ -1 }\equiv 0(mod\quad p)kr1+i10(modp)
那么我们移动一下位置就有{ i }^{ -1 }\equiv -k{ r }^{ -1 }(mod\quad p)i1kr1(modp)
最后转换一下kk就有{ i }^{ -1 }\equiv -\left\lfloor \frac { p }{ i } \right\rfloor { (p\quad mod\quad i) }^{ -1 }(mod\quad p)i1pi(pmodi)1(modp),然后就可以啦.代码就不用我说了吧.

  • 矩阵乘法
    关于这个我不想多讲,直接看百度吧:矩阵乘法

代码如下:

#define REP(i,s,t) for(int i=s;i<=t;i++)matrix mul(matrix A,matrix B){    matrix ret;    memset(ret.mtx,0,sizeof ret.mtx);    REP(i,1,n)REP(j,1,n)REP(k,1,n)        ret.mtx[i][j]=(ret.mtx[i][j]+A.mtx[i][k]*B.mtx[k][j]);    return ret;}
  • 高斯消元
    高斯消元是一个十分玄学的东西,但是也不是什么特别高深的东西,实际上就是在解一个线性方程组,也就是说将二元一次方程组扩展到n元一次方程组来求解.实际步骤和重复地加减消元没有太多差别.不过为了方便地表示,我们还是先来了解几个概念.

  • 1.增广矩阵
    我们可以先用矩阵的方法表示一个线性方程组,如图所示:

a1b1...p1q1a2b2...p2q2...............an1bn1...pn1qn1anbn...pnqnx1x2...xn1xn=A1A2...An1An

这是什么,这就是线性方程组用矩阵乘法的表现形式,但是我们还是有点嫌麻烦,于是我们在原有的矩阵基础上在开一维,就形成了增广矩阵,大概就是这个样子:

a1b1...p1q1a2b2...p2q2...............an1bn1...pn1qn1anbn...pnqn|||||A1A2...An1An

  • 2.消元步骤
    接下来就是高斯消元的核心步骤了,我们的目标就是让每一行都只保留一个系数,形成一个对角线的样子,就像这样:

a10...000b2...00...............00...pn1000...0qn|||||A1A2...An1An

当然,这只是一种情况,还有其他的像”上三角形式”之类的我就不说了,应该也是可以变成这种样子的.对于这个方程组我们是可以一目了然地得到方程的解,那么具体来说我们怎么得到呢?我们看到第一列,由于第一列中只有第一行保留系数,那么我们可以强行消掉将除第一个方程以外所有的第一项系数,之后对于每一个方程都这么做一遍就可以了.

代码如下:

bool gauss(){    for(int i=0;i<n;i++){        int k=i;        for(int j=i+1;j<n;j++)            if(fabs(matrix[j][i])>fabs(matrix[k][i]))k=j;        if(fabs(now=matrix[k][i])<MIN)return true;        for(int j=i;j<=n;j++)swap(matrix[i][j],matrix[k][j]);        for(int j=i;j<=n;j++)matrix[i][j]/=now;        for(int k=0;k<n;k++){            if(k!=i){                now=matrix[k][i];                for(int j=i;j<=n;j++)matrix[k][j]-=matrix[i][j]*now;            }        }    }    return false;}
1 0