• 数论同余学习笔记 Part 3


    中国剩余定理

    解同余方程组 \(\begin{cases}x\equiv a_1\pmod{m_1}\\ x\equiv a_2\pmod{m_2}\\ \qquad\cdots\\ x\equiv a_n\pmod{m_n}\end{cases}\)
    其中 \(m_i\) 两两互质。

    \(M=\prod\limits_{i=1}^nm_i\)\(M_i=\prod\limits_{j\ne i}m_j=\dfrac M{m_i}\)
    \(M_i^{-1}\) 表示 \(M_i\bmod m_i\) 的逆元(注意模数),则方程组的解为

    \[x\equiv \sum_{i=1}^na_iM_iM_i^{-1}\pmod M \]

    正确性不难验证

    模板题:洛谷P1495 【模板】中国剩余定理(CRT)/曹冲养猪

    扩展中国剩余定理

    方程组同上,但不保证 \(m_i\) 两两互质。
    核心思想在于合并两个同余方程的操作

    \(\begin{cases}x\equiv a_1\pmod{m_1}\\ x\equiv a_2\pmod{m_2}\end{cases}\) 为例

    \(x=m_1k_1+a_1=m_2k_2+a_2\),则 \(m_1k_1-m_2k_2=a_2-a_1\)
    经典的二元一次不定方程。无解条件是 \(\gcd(m_1,m_2)\nmid a_2-a_1\)

    如果有解,可用 exgcd 得到一组可行解 \(k_1,k_2\)
    列出新方程:\(x\equiv m_1k_1+a_1\pmod{{\rm lcm}(m_1,m_2)}\)
    这样就将两个方程合并成了一个。\(n-1\) 次合并之后即可求出原方程组的解。

    模板题:洛谷P4777 【模板】扩展中国剩余定理(EXCRT)

    BSGS

    求方程 \(a^x\equiv b\pmod p\) 的最小非负整数解。其中 \(a,p\) 互质。

    考虑欧拉定理:\(a,p\) 互质时,\(a^{\varphi(p)}\equiv 1\pmod p\)

    易知最小非负整数解一定在 \([0,p)\) 内,如果这个区间内找不到解那就是无解。

    \(x=im-j(1\le j\le m)\),其中 \(m=\lceil\sqrt p\rceil\),则

    \[a^x\equiv b\Longleftrightarrow (a^m)^i\equiv b\cdot a^j \]

    枚举 \(j=1\sim m\) 并计算 \(b\cdot a^j\) 的值,存入 hash 表;
    枚举 \(i=1\sim m\),计算 \((a^m)^i\) 的值,查表寻找解。

    枚举顺序为从小到大,并且当 \(b\cdot a^j\) 的值出现重复时,用较大的 \(j\) 覆盖较小的。
    这样就保证了最先找到的一定是最小非负整数解。没找到则无解。

    时间复杂度 \(O(\sqrt p)\),如果 hash 表是用 map 实现的就带个 log

    模板题:洛谷P3846 [TJOI2007] 可爱的质数/【模板】BSGS

    exBSGS

    求方程 \(a^x\equiv b\pmod p\) 的最小非负整数解。不保证 \(a,p\) 互质。

    \(g=\gcd(a,p)\)

    \[a^x\equiv b\pmod p\Longleftrightarrow \tfrac{a^x}g\equiv \tfrac bg\pmod{\tfrac pg} \]

    \(g\nmid b\) 时是无解的。

    \[a^{x-1}\equiv \frac bg\cdot\left(\frac ag\right)^{-1}\pmod{\tfrac pg} \]

    由于 \(\dfrac ag\)\(\dfrac pg\) 互质,逆元一定存在。

    此时得到的方程与原方程形式相同,但模数变为了 \(\dfrac pg\)
    容易想到递归处理,直到 \(a\) 与模数互质,即可用 BSGS 解决。

    \(p\) 变为 \(\dfrac pg\) 至少减半,因此递归层数 \(k\) 不超过 \(\log p\)

    实际上还要考虑 \(x<k\) 的情况,所以先枚举 \(x=0\sim k\),判断是否存在解,有解则直接返回,否则再执行上述过程。

    时间复杂度一般为 \(O(\sqrt p)\),瓶颈在底层的 BSGS 。

    模板题:洛谷P4195 【模板】扩展 BSGS/exBSGS

    代码还是挺细节的,,贴一下吧(虽然丑得没法看

    实际上式子化为 \(\displaystyle{a^{x-k}\cdot\prod\frac ag\equiv \frac b{\prod g}\pmod{\frac p{\prod g}}}\) 就可以用 BSGS 做了,没必要求逆元

    #include<stdio.h>
    #include<math.h>
    const int P=10007;
    int a,b,p,x,y,g,m,k,t,t2,s,cnt,lst[P];
    struct node { int x,j,pre; }mp[40000]; // 手写 hash 表
    inline void ins(int x,int j) { // insert
        mp[++cnt]={x,j,lst[x%P]},lst[x%P]=cnt;
    }
    inline int fnd(int x) { // find
        for (int i=lst[x%P]; i; i=mp[i].pre)
            if (mp[i].x==x) return mp[i].j;
        return 0;
    }
    
    int gcd(int x,int y) { return y?gcd(y,x%y):x; }
    void exBSGS(int a,int b,int p) {
        if (b==1) { puts("0"); return ; } // 需要特判
        for (int i=1; i<=cnt; ++i) lst[mp[i].x%P]=0;
        s=t=1,k=0,cnt=0;
        while ((g=gcd(a,p))!=1) {
            if (b%g) { puts("No Solution"); return ; }
            t=1ll*t*(a/g)%(p/=g),b/=g,++k;
            if (t==b) { printf("%d\n",k); return ; }
        }
        m=ceil(sqrt(p));
        for (int i=1; i<=m; ++i)
            s=1ll*s*a%p,ins(1ll*s*b%p,i);
        for (int i=1; i<=m; ++i) // 循环开始时 t 的值即为 Π(a/g)
            if (t2=fnd(t=1ll*t*s%p)) { 
                printf("%d\n",i*m-t2+k);
                return ;
            }
        puts("No Solution");
    }
    int main() {
        scanf("%d%d%d",&a,&p,&b);
        while (p)
            exBSGS(a%p,b%p,p),
            scanf("%d%d%d",&a,&p,&b);
        return 0;
    }
    
  • 相关阅读:
    凭什么要用面向对象编程(补充)
    一篇面试题文章引发的“争议”
    伍迷创意随想集 之 杯具拥有个性,个性成就杯具
    Apple Mac OS X每日一技巧016:MacBook电源线如何缠绕
    Apple Mac OS X每日一技巧008:快速调整/删除菜单栏上的图标
    《C#妹妹和ObjectiveC阿姨对话录》(05)自动释放池--拆迁队的外援
    Apple Mac OS X每日一技巧005:Photo Booth把你的Mac当成照相机
    Apple Mac OS X每日一技巧010:查看本机的版本、版号和序列号
    Apple Mac OS X每日一技巧009:option键和菜单栏的系统图标
    Apple Mac OS X每日一技巧004:抓屏那点事(截屏/抓图/截图)
  • 原文地址:https://www.cnblogs.com/REKonib/p/15885872.html
Copyright © 2020-2023  润新知