首页 > 其他分享 >浅谈同余3(扩展中国剩余定理,扩展BSGS)

浅谈同余3(扩展中国剩余定理,扩展BSGS)

时间:2023-05-21 13:14:49浏览次数:51  
标签:cnt return 浅谈 int res LL 扩展 pmod BSGS


距离上一篇已经四个月了,我来填坑了

上一篇:$浅谈同余2(扩展欧几里得,中国剩余定理,BSGS)$

(https://www.cnblogs.com/xyy-yyds/p/17418472.html)

0x50 扩展BSGS $O(\sqrt n)$


【模板】扩展 BSGS/exBSGS

 题目背景

题目来源:SPOJ3105 Mod

题目描述

给定 $a,p,b$,求满足 $a^x≡b \pmod p$ 的最小自然数 $x$ 。

输入格式

每个测试文件中包含若干组测试数据,保证 $\sum \sqrt p\le 5\times 10^6$。

每组数据中,每行包含 $3$ 个正整数 $a,p,b$ 。

当 $a=p=b=0$ 时,表示测试数据读入完全。

输出格式

对于每组数据,输出一行。

如果无解,输出 $No\text{ }Solution$,否则输出最小自然数解。

样例输入 #1

5 58 33
2 4 3
0 0 0

样例输出 #1

9
No Solution

提示

对于 $100\%$ 的数据,$1\le a,p,b≤10^9$ 或 $a=p=b=0$。

2021/5/14 加强 by [SSerxhs](https://www.luogu.com.cn/user/29826)。
2021/7/1 新添加[一组 Hack 数据](https://www.luogu.com.cn/discuss/391666)。

本题$a, p$不互质,所以我们要把$a, p$变得互质
即除去它们的公因数
当然,根据$B\acute{e}zout$定理当$\gcd(a, p) \nmid b$时,方程无解
即求$\frac{a^x}{d} \equiv \frac{b}{d} \pmod {\frac{p}{d}}$ 的答案再加上除的次数就是答案
也可以写成$a ^ {x - cnt} \cdot \frac{a ^ {cnt}}{d} \equiv \frac{b}{d} \pmod {\frac{p}{d}}$
$\frac{a ^ cnt}{d}$要当参数传进去,即代码里的add

注意,本题卡常,此代码要开$C++20 + O2$才能过
我才不会告诉你这道题我卡了一屏TLE呢
$Code:$

#include <iostream>
#include <unordered_map>
#include <cmath>

using namespace std;

typedef long long LL;

inline int read()
{
    register int s = 0, f = 1;
    register char c = getchar();
    for ( ; !isdigit(c); c = getchar())  if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar())   s = (s << 1) + (s << 3) + (c ^ 48);
    return s * f;
}

inline int qmi(int a, int b, int p)
{
    register int res = 1 % p;
    
    while (b)
    {
        if (b & 1) res = (LL)res * a % p;
        
        b >>= 1;
        a = (LL)a * a % p;
    }
    
    return res;
}

unordered_map<int, int> Hash;
inline int bsgs(int a, int b, int p, int add) //普通BSGS
{
    Hash.clear();
    
    register int t = (int)sqrt(p) + 1;
    register int tmp = 1;
    for (register int j = 0; j < t; j ++ )
    {
        int val = (LL)b * tmp % p;
        Hash[val] = j;
        tmp = (LL)tmp * a % p; //递推减少快速幂的log
    }

    a = qmi(a, t, p);
    tmp = 1;
    for (register int i = 0; i <= t; i ++ )
    {
        int val = (LL)add * tmp % p; //同上
        int j = Hash.find(val) == Hash.end() ? -1 : Hash[val];
        
        if (j >= 0 && i * t - j >= 0) return i * t - j;
        tmp = (LL)tmp * a % p;
    }
    
    return -1;
}

inline int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

inline int exbsgs(int a, int b, int p)
{
    a %= p, b %= p;
    if (b == 1 || p == 1) return 0;
    
    register int cnt = 0;
    register int d, add = 1;
    
    while ((d = gcd(a, p)) ^ 1) //消除因子
    {
        if (b % d) return -1; //bezout判无解
        cnt ++, b /= d, p /= d;
        add = (LL)add * a / d % p; //a^cnt / d
        
        if (add == b) return cnt;
    }
    
    int res = bsgs(a, b, p, add);
    if (res == -1) return -1;
    return res + cnt; //别忘记+cnt
}

int main()
{
    int a, b, p, res;
    a = read(), p = read(), b = read();
    while (a || b || p)
    {
        res = exbsgs(a, b, p);
        
        if (res == -1) puts("No Solution");
        else printf("%d\n", res);
        
        a = read(), p = read(), b = read();
    }
    
    return 0;
}

 

0x60 扩展中国剩余定理
求方程组
$$
\begin{cases}
x \equiv {a_1} \pmod {m_1} \\\
x \equiv {a_2} \pmod {m_2} \\\
x \equiv {a_3} \pmod {m_3} \\\
...\\\
x \equiv {a_n} \pmod {m_n} \\\
\end{cases}
$$
的最小整数解,其中$m_1, m_2, ..., m_n$不两两互质

设之前$1 \sim {i - 1}$个方程的解为$x$
前$i - 1$方程的通解可以表示为$x + i * M$, 其中$M = \operatorname{lcm}\\{m_1, m_2, ..., m_{i - 1}\\} $
与$i$个方程合并,可得方程
$x + k * M \equiv a_i \pmod {m_i}$
这就是同余方程,可用$exgcd$求解,然后$x$加上$k * M$就是前$i$个方程的解
要求最小解,所以要对$M$取模

具体可以去看进阶指南和墨染空巨佬的这个(https://www.acwing.com/solution/content/3539/)

以洛谷模板P4777 【模板】扩展中国剩余定理(EXCRT)为例
由于数据范围很大,要炸$long \text{ } long$, 所以要用$int128$
$Code:$

#include <iostream>
#include <cstring>

using namespace std;

typedef __int128 LL;

int n;

LL exgcd(LL a, LL b, LL &x, LL &y) //扩展欧几里得
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }
    
    LL d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    
    return d;
}

LL gcd(LL a, LL b)
{
    return b ? gcd(b, a % b) : a;
}

LL lcm(LL a, LL b)
{
    return a / gcd(a, b) * b;
}

int main()
{
    scanf("%d", &n);
    
    LL a1, m1, a2, m2, x, y;
    // x mod m1 = a1
    long long M, A;
    scanf("%lld%lld", &M, &A);
    m1 = M, a1 = A;
    
    for (int i = 2; i <= n; i ++ )
    {
        scanf("%lld%lld", &M, &A);
        m2 = M, a2 = A;
        
        LL d = exgcd(m1, m2, x, y);
        if ((a2 - a1) % d) //bezout判无解
        {
            puts("-1");
            return 0;
        }
        
        x = x * (a2 - a1) / d % (m2 / d);
        if (x < 0) x += m2 / d;
        
        LL mod = lcm(m1, m2);
        a1 = (m1 * x + a1) % mod;
        if (a1 < 0) a1 += mod;
        m1 = mod;
    }
    
    printf("%lld\n", (long long)(a1 % m1));
    
    return 0;
}

 

标签:cnt,return,浅谈,int,res,LL,扩展,pmod,BSGS
From: https://www.cnblogs.com/xyy-yyds/p/17418478.html

相关文章

  • 浅谈同余1(常用定理和乘法逆元)
    点个赞吧,球球了~下一篇:$浅谈同余2(扩展欧几里得,中国剩余定理,BSGS)$https://www.acwing.com/file_system/file/content/whole/index/content/7882318/ $\LaTeX$太多了,分成几个部分0x00总写(瞎说)同余是数学中非常重要的东西,这里会写出同余的基本运用若$a\bmodm=b\bmo......
  • 标准库中的生成器函数——用于扩展元素的生成器函数
      1  combinations:组合数最少的;组合数的下限,重复没有意义(所以不存在AA,BB,CC这种组合),元素的顺序也没意义(AB和BA是一种组合);product:返回笛卡尔积,组合数最多的,组合数的上限,重复和元素的顺序都有意义;combinations_with_replacement:重复有意义(所以存在AA,BB,CC这种组合),元......
  • From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
    FromJavaToKotlin,空安全、扩展、函数、Lambda概述(Summarize)• Kotlin是什么?• 可以做什么?• Android官方开发语言从Java变为Kotlin,Java有哪些问题?• Kotlin的优点• Kotlin特性(Features)Kotlin是什么?Kotlin出自于捷克一家软件研发公司 JetB......
  • 浅谈物联网平台的重要性以及建设展望
    随着物联网(InternetofThings,简称IoT)技术的快速发展,物联网平台已成为连接各种设备,处理大量数据,并为用户提供智能服务的关键工具。在此背景下,深入理解物联网平台的重要性,以及对其未来建设的展望显得尤为重要。物联网平台在链接设备、管理数据以及提供服务等方面具有重要价值:在设......
  • linux(RK3308)添加CH9434(SPI串口扩展)驱动
    linux(RK3308)添加CH9434(SPI串口扩展)驱动1、CH9434驱动下载https://www.wch.cn/downloads/CH9434EVT_ZIP.html2、驱动移植2.1、移植准备1、查看系统是否支持DTS设备树支持,若支持DTS可以直接在DTS文件中定义SPI节点。如下所示:&spi2{status="okay";max-freq=<500......
  • 浅谈 OI 中各种合并操作
    前言合并操作一直是OI中一大考点,今天请各位跟着笔者来梳理一下各种合并操作。启发式合并几乎可以说是最经典的合并了。假定我们可以在\(O(k)\)的时间内往某个集合中插入一个数,那么我们就可以在\(O(n\lognk)\)的时间内合并若干个元素总量为\(n\)的集合。集合启发式......
  • 浅谈一类信息的暴力重构手法
    loj#6515.「雅礼集训2018Day10」贪玩蓝月背包支持类似栈的加入与撤销(由于是最优化,不太能直接删除),而题目要求维护双端队列式的操作,这是一个经典问题——双栈模拟双端队列(也叫bakatrick)。直接给出方法:维护两个栈,两栈的拼接即为我们维护的队列,照常进行大部分操作,若某一栈在空......
  • Stable Diffusion 的 ControlNet 扩展
    本文介绍如何安装ControlNet扩展?和ControlNet的模型安装,同时给了两个例子。一、ControlNet扩展安装进入StableDiffusion界面,点击扩展标签,选择从URL安装,然后输入ControlNet网址(https://github.com/Mikubill/sd-webui-controlnet),粘贴到对应的地方,然后点击安装。完成......
  • [转载]lsattr -I -e 文件扩展属性的一些解释
    排查时遇到的问题此文章做出了一些解答,转载以作为记录,源文章地址https://blog.systemctl.top/2017/2017-04-14_something-about-lsattr_-i_-e/1.如图e是什么?I又代表什么?这个问题我觉得不是个难问题,简单man下就出来了,可问题来了,更多的系列问题更是随之而来…manlsattr......
  • 打包谷歌浏览器的扩展程序
    1.打开浏览器工具的拓展程序 2.先找到谷歌浏览器拓展程序的位置在哪谷歌浏览器地址栏输入:chrome:version   3.记住拓展程序的id,找到所在的文件夹的对应id文件名  4.随后打开该插件ID所在的路径,进一步打开该插件的版本号文件夹,然后复制地址栏上的完整路径。 ......