• 技术文章 >后端开发 >Python教程

    计算机程序的算法小记

    巴扎黑巴扎黑2017-07-17 11:07:15原创1163

    什么是计算机程序设计?

      简单的说,它就是告诉计算机要做什么。计算机可以做很多事情,但是不太擅长自主思考,程序员需要像给小孩子喂饭一样告诉它具体的细节,并且使计算机能够理解的语言——算法。

      算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
      算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个终态。一个状态到另一个状态的转移不一定是确定的。随机化算法在内的一些算法,包含了一些随机输入。
      形式化算法的概念部分源自尝试解决希尔伯特提出的判定问题,并在其后尝试定义有效计算性或者有效方法中成形。这些尝试包括库尔特·哥德尔、Jacques Herbrand和斯蒂芬·科尔·克莱尼分别于1930年、1934年和1935年提出的递归函数,阿隆佐·邱奇于1936年提出的λ演算,1936年Emil Leon Post的Formulation 1和艾伦·图灵1937年提出的图灵机。即使在当前,依然常有直觉想法难以定义为形式化算法的情况。

    特征

      一个算法应该具有以下五个重要的特征:
      1、有穷性(Finiteness)
        算法的有穷性是指算法必须能在执行有限个步骤之后终止;
      2、确切性(Definiteness)
        算法的每一步骤必须有确切的定义;
      3、输入项(Input)
        一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;
      4、输出项(Output)
        一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
      5、可行性(Effectiveness)
        算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性)。

    要素

      一,数据对象的运算和操作:计算机可以执行的基本操作是以指令的形式描述的。一个计算机系统能执行的所有指令的集合,成为该计算机系统的指令系统。一个计算机的基本运算和操作有如下四类:
        1,算术运算:加减乘除等运算
        2,逻辑运算:或、且、非等运算
        3,关系运算:大于、小于、等于、不等于等运算
        4,数据传输:输入、输出、赋值等运算[1]
      二,算法的控制结构:一个算法的功能结构不仅取决于所选用的操作,而且还与各操作之间的执行顺序有关。

    分类

      算法可大致分为基本算法、数据结构的算法、数论与代数算法、计算几何的算法、图论的算法、动态规划以及数值分析、加密算法、排序算法、检索算法、随机化算法、并行算法,厄米变形模型,随机森林算法。
      算法可以宏泛的分为三类:
        一,有限的,确定性算法 这类算法在有限的一段时间内终止。他们可能要花很长时间来执行指定的任务,但仍将在一定的时间内终止。这类算法得出的结果常取决于输入值。
        二,有限的,非确定算法 这类算法在有限的时间内终止。然而,对于一个(或一些)给定的数值,算法的结果并不是唯一的或确定的。
        三,无限的算法 是那些由于没有定义终止定义条件,或定义的条件无法由输入的数据满足而不终止运行的算法。通常,无限算法的产生是由于未能确定的定义终止条件。

    基础数论储备

    二次剩余

    首先来看一个式子x2≡n(modp),我们现在给出n,要求求得x的值。如果可以求得,n为mod p的二次剩余,其实就是n在mod p意义下开的尽方。Cipolla就是一个用来求得上式的x的一个算法。

    勒让德符号

    勒让德符号是判断一个数是否为p的二次剩余的一个有力工具,p一定要为奇质数。(n,p)表示n为关于p的勒让德符号。其实就是判断n是否为p的二次剩余。

    (np)=⎧⎩⎨1——p不是n的倍数,n是p的二次剩余−1——p不是n的倍数,n是p的二次非剩余(不是二次剩余就是非剩余)0——p是n的倍数


    看起来好像是一大段废话,勒让德只是站在巨人的肩膀上总结了一下而已。
    其实勒让德还总结了一些性质,不过一般只用得到欧拉判别准则,不够勒让德符号是个积性函数可能还有点用。
    但还是不知道如何判断n是否为p的二次剩余,往下看欧拉判别准则

    ll Legendre(ll a, ll p)
    {
    return qsm(a, (p-1)/2, p);
    } 12341234

    欧拉判别准则

    先来回顾一下欧拉定理xφ(p)≡1(modp)
    因为这里的p是奇质数,所以xp−1≡1(modp)
    对xp−1进行开方操作,在虚数域中xp−12≡±1(modp),如果等于1就肯定开的了方,为-1一定开不了。所以x是否为n的二次剩余就用这个欧拉判别准则。

    if(qsm(n,(p-1)/2)==p-1){ printf("No root\n");
    continue;
    }12341234

    -1在mod p意义下为p-1。

    算法流程

    给出n和p
    就算我们n关于p的勒让德符号为1,那么要怎样取开n的方呢?
    现在是脑洞大开的时候。

    找一个数a

    我们随机一个数a,然后对a2−n进行开方操作(就是计算他勒让德符号的值),直到他们的勒让德符号为-1为止(就是开不了方为止)。
    就是找到一个a满足(a2−n)p−12=−1
    先不要管为什么,后面会讲,我们现在就默默的去膜拜Cipolla的脑洞很大。

    while(1){
    a=rand()%p;
    w=(a*a-n+p)%p; if(qsm(w,(p-1)/2)==p-1)break;
    }1234512345

    因为是随机找a,那么会不会要找很久。
    答案:不会!
    ∙定理1:x2≡n(modp)中有p−12个n能使方程有解
    ⇒证明定理1:x2≡n(modp),如果存在不同的数u,v,使他们带入x后可以使方程有解,那么很显然满足u2−v2|p,所以满足(u+v)(u−v)|p,因为
    u2−v2|p所以p不可能是(u-v)的倍数,所以(u+v)|p,那么这样的数对在p中存在的数量为p−12
    根据定理1,随机找a的期望为2。

    建立一个复数域

    说是建立,其实根本不用程序去打,说是建立复数域只是跟方便理解。
    在平常学的复数域中,有一个i,满足i2=−1。
    我们也建立一个类似的域,因为我们要对于a2−n开方,而a2−n有不是p的二次剩余,所以我们定义ω=a2−n−−−−−√。那么现在的ω也像i一样,满足ω2=a2−n,这样我们就定义了一个新的域。

    struct CN{
    ll x,y;
    CN friend operator *(CN x,CN y){
    CN z;
    z.x=(x.x*y.x%p+x.y*y.y%p*w%p)%p;
    z.y=(x.x*y.y%p+x.y*y.x%p)%p; return z;
    }
    }u,v;123456789123456789

    像正常打复数运算一样我们定义一下运算符。可以发现z.x那个地方后面是*w而不是*1,因为现在的域单位复数为ω,满足ω2=a2−n,而不像正常复数的i2=−1。在这个域中的表示方式类似正常的复数:a+bω

    得出答案

    我们要求的是x2≡n(modp),x的值
    我们现在知道了a和ω之后,就能得出答案了。
    答案=(a+ω)p+12
    真的吗?真的!但是这个答案不是由实数和虚数组成的吗?
    根据拉格朗日定理,可以得出虚数处的系数一定为0。

    CN Cqsm(CN x,ll y){\\复数的快速幂 CN z;z.x=1,z.y=0;\\注意初始化 while(y){ if(y&1)z=z*x;
    x=x*x;
    y/=2;
    } return z;
    }123456789123456789
    w=(a*a-n+p)%p;
    u.x=a,u.y=1;//为什么u.y是1——在复数的统计中只用统计系数就好了
    u=Cqsm(u,(p+1)/2);
    ll yi=u.x,er=p-u.x; if(yi>er)swap(yi,er); if(yi==er){ printf("%lld\n",yi);
    } else{ printf("%lld %lld\n",yi,er);
    }12345678910111234567891011

    为什么会有两个答案,比如4√=±2,x2≡(p−x)2(modp)很显然,因为把后面拆开x2≡x2−2px+p2(modp),把p都约去,所以x2≡(p−x)2(modp)。

    证明原理

    再搞出一些定理方便说明。

    定理

    ∙定理2:(a+b)p≡ap+bp(modp)
    ⇒证明定理2:根据二项式定理:
    (a+b)p≡∑pi=0Cipap−ibi(modp)
    ≡∑pi=0p!(p−i)!i!ap−ibi(modp)
    可以发现,只有当i=0或i=p的时候式子没有p的因子,所以中间有p的因子的都可以省略,所以(a+b)p≡ap+bp(modp)
    ∙定理3:ωp≡−ω(modp)
    ⇒证明定理3:ωp
    =ωp−1∗ω
    =(ω2)p−12∗ω
    =(a2−n)p−12∗ω——因为ω2=a2−n
    =−ω——因为满足(a2−n)p−12=−1
    ∙定理4:ap≡a(modp)
    ⇒证明定理3:ap根据费马小定理
    ≡ap−1≡1(modp)
    所以ap≡a∗ap−1≡a(modp)

    推导

    问题:x2≡n(modp)求解x
    Cipolla:x≡(a+ω)p+12(modp)的实数
    直接把式子转化:
    (a+ω)p+12(modp)
    ≡((a+ω)p+1)12(modp)
    ≡((a+ω)p(a+ω))12(modp)
    ≡((ap+ωp)(a+ω))12(modp)根据定理2
    ≡((a−ω)(a+ω))12(modp)根据定理3和定理4
    ≡(a2−ω2)12(modp)根据定理3和定理4
    ≡(a2−(a2−n))12(modp)满足ω2=a2−n
    ≡n12(modp)
    所以(a+ω)p+12≡n12≡n√(modp)
    这脑洞太大了!!!!!!!!!!!!!!


    php入门到就业线上直播课:查看学习

    以上就是计算机程序的算法小记的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    专题推荐:小记 算法
    上一篇:Python列表List 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• Python NumPy教程之数据类型对象• 使用Python处理KNN分类算法• Python标准库中的logging用法示例• python发腾讯微博代码分享• python自动化测试实例解析
    1/1

    PHP中文网