• 数学专题总结


    数学专题总结#

    • 扩展欧几里得算法
      扩展欧几里得算法就是用来求解不定方程(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互质的数的个数的函数.函数具体为:
      (varphi (n)=n(1-frac { 1 }{ { p }_{ 1 } } )(1-frac { 1 }{ { p }_{ 2 } } )...(1-frac { 1 }{ { p }_{ k } } ))
      其中(p1)-(pk)都表示n的质因数.
      并且欧拉函数是积性函数,即(varphi (ab)=varphi (a)varphi (b)quad (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);
    	    	}
    		}
        }
    }
    
    • 逆元
      这里的逆元我主要指的是模意义下的逆元.如果(axequiv 1(modquad p)),我们就称(a)对于(p)的逆元为(x),记作({ a }^{ -1 }),可以形象地认为它就是(a)在模意义下的倒数.求逆元可以用扩展欧几里得算法,不过我重点要介绍一种线性求逆元的方法.即在线性的时间内求出1-p-1的所有逆元,且p为质数.

    我们可以设(p=ki+r)
    那么显然有(ki+requiv 0(modquad p))
    我们两边同时乘上一个({ i }^{ -1 }{ r }^{ -1 })
    那么就有(k{ r }^{ -1 }+{ i }^{ -1 }equiv 0(modquad p))
    那么我们移动一下位置就有({ i }^{ -1 }equiv -k{ r }^{ -1 }(modquad p))
    最后转换一下(k)就有({ i }^{ -1 }equiv -leftlfloor frac { p }{ i } ight floor { (pquad modquad i) }^{ -1 }(modquad p)),然后就可以啦.代码就不用我说了吧.

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

    代码如下:

    
    #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.增广矩阵
      我们可以先用矩阵的方法表示一个线性方程组,如图所示:

    (egin{bmatrix} { a }_{ 1 } & { a }_{ 2 } & ... & { a }_{ n-1 } & { a }_{ n } \ { b }_{ 1 } & { b }_{ 2 } & ... & { b }_{ n-1 } & { b }_{ n } \ ... & ... & ... & ... & ... \ { p }_{ 1 } & { p }_{ 2 } & ... & { p }_{ n-1 } & { p }_{ n } \ { q }_{ 1 } & { q }_{ 2 } & { ... } & { q }_{ n-1 } & { q }_{ n } end{bmatrix}egin{bmatrix} { x }_{ 1 } \ { x }_{ 2 } \ ... \ { x }_{ n-1 } \ { x }_{ n } end{bmatrix}=egin{bmatrix} { A }_{ 1 } \ { A }_{ 2 } \ ... \ { A }_{ n-1 } \ { A }_{ n } end{bmatrix})

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

    (egin{bmatrix} { a }_{ 1 } & { a }_{ 2 } & ... & { a }_{ n-1 } & { a }_{ n } & | & { A }_{ 1 } \ { b }_{ 1 } & { b }_{ 2 } & ... & { b }_{ n-1 } & { b }_{ n } & | & { A }_{ 2 } \ ... & ... & ... & ... & ... & | & ... \ { p }_{ 1 } & { p }_{ 2 } & ... & { p }_{ n-1 } & { p }_{ n } & | & { A }_{ n-1 } \ { q }_{ 1 } & { q }_{ 2 } & { ... } & { q }_{ n-1 } & { q }_{ n } & | & { A }_{ n } end{bmatrix})

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

    (egin{bmatrix} { a }_{ 1 } & 0 & ... & 0 & 0 & | & { A }_{ 1 } \ 0 & { b }_{ 2 } & ... & 0 & 0 & | & { A }_{ 2 } \ ... & ... & ... & ... & ... & | & ... \ 0 & 0 & ... & { p }_{ n-1 } & 0 & | & { A }_{ n-1 } \ 0 & 0 & { ... } & 0 & { q }_{ n } & | & { A }_{ n } end{bmatrix})

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

    代码如下:

    
    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;
    }
    
    
  • 相关阅读:
    多线程间通信之AutoResetEvent和ManualResetEvent的原理分析和开发示例
    【推荐】基于WebActivator的改进版本KudyStudio.Web.Activating讲解与源码下载
    Visual Studio中你所不知道的智能感知
    压缩网页图片
    二叉树
    DynamicXml 动态读取操作XML (一个从XML到Object的通用实现)
    张剑微软2011 GCR MVP Open Day 之旅!【转载】
    使用Solr构建企业级的全文检索
    jQuery版仿Path菜单发布!
    使用maven进行开发过程管理之准备篇
  • 原文地址:https://www.cnblogs.com/Exbilar/p/6592009.html
Copyright © 2020-2023  润新知