zoukankan      html  css  js  c++  java
  • 数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)

    什么叫高次同余方程?说白了就是解决这样一个问题:

    A^x=B(mod C),求最小的x值。


    baby step giant step算法

    题目条件:C是素数(事实上,A与C互质就可以。为什么?在BSGS算法中是要求a^m在%c条件下的逆元的,如果a、c不互质根本就没有逆元。

    如果x有解,那么0<=x<C,为什么?

    我们可以回忆一下欧拉定理:

    对于c是素数的情况,φ(c)=c-1

    那么既然我们知道a^0=1,a^φ(c)=1(在%c的条件下)。那么0~φ(c)必定是一个循环节(不一定是最小的)。既然是%c,那么B一定是0到c-1之间的一个数。最坏的条件下,a的φ(c)以内次方%c的余数各不相同,0<=x<C时一定存在一个x满足条件。根据抽屉原理,如果在大于c的x中出现一个x值满足条件,那在它以前一定有一个更小的x值满足条件。

    BSGS的算法是这样的:

    首先取m=sqrt(c)向上取整。(为什么取sqrt(c)?我也不是很懂,是为了算法的效率平衡。)

    然后先预处理a的0到m次方。

    a^x=b ( %c )
    设x=i*m+j;
    即: i为x/m,j为x%m。
    a^(i*m+j)=b;
    b * (a^(-m))^i = a^j ( %c )

    先枚举j,把右边存起来(Hash 或者 普通数组,下一步用二分查找)
    枚举i,如果左边的数值曾经存储过(b * (a^(-m))^i = a^j),则 x=i*m+j。

    求a^(-m):(就是a^m的逆元)

    有两种方法:

       方法一:根据欧拉定理

                    设A=a^m,那么A^φ(c)==1(%c)

                    A^(φ(c)-1)*A==1(%c)

                   到这里已经可以得到A的逆元为A^(φ(c)-1)。

                   继续推下去,根据c是素数,φ(c)=c-1

                   那么A的逆元就是A^(c-2)

         

       方法二:相当于解a^m*x-C*y=1,根据拓展欧几里得出x就是逆元。

    BSGS主要就是要注意细节,注意要去重(余数相同时只要取较小的一个)。


    拓展BSGS

    如果a跟c不互质,那该怎么办?

    其实只需要加一小段代码就可以。

    首先,我们知道:

    A%C=B,那么就是A-C*x=B,如果d=gcd(A,C),且B%d==0,那么(A/d)%(C/d)=B/d是成立的。

    那么我们就在A与C仍有不为一的公因数的时候,不断地从a^x中拿出一个a与c约分。过程中如果b%d!=0,那么在x>T的时候无解。

    LL D=1%C; LL g=0,d;
    while(  ( d=gcd(A,C)   )  !=1 )
    {        
            if(B%d)return -1;
            B/=d;C/=d;
            g++;D=D*(A/d)%C;
    }
    View Code

    最后我们的方程就变为了k*a^(x-g) == b' (%c')

    用BSGS解出x后加上g就是答案。

  • 相关阅读:
    JS—图片压缩上传(单张)
    vue 使用jssdk分享
    微信JS-SDK选择图片遇到的坑
    手把手教你实现一个微信自动回复机器人
    SSH实现远程控制
    使用Apache服务部署静态网站
    Rhel7安装及网卡、yum、vmtools配置和修改主机名
    基础工具之消息队列、线程池、缓冲区抽象、事件循环和日志实现
    I/O多路复用方案
    Java按字节截取字符串(GBK编码、UTF-8编码实现)
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5178600.html
Copyright © 2011-2022 走看看