• 数论同余学习笔记 Part 1


    GCD

    辗转相除法求。时间复杂度 \(O(\log M)\)\(M\) 为数的值域)

    int gcd(int x,int y) { return y?gcd(y,x%y):x; }
    

    随机数据下跑不满。如果要把它卡满,构造数据使 \(x,y\) 为 Fibonacci 数列的连续两项即可。

    [SDOI2009]SuperGCD

    题意简述:求两个不超过 \(10^{10000}\) 的正整数的 gcd 。

    如果用辗转相除,必然要手写高精除、高精模,感觉很麻烦

    考虑带优化的更相减损术(也被称为辗转相减):

    \[\gcd(x,y)=\begin{cases} 2\gcd(x/2,y/2)& (2\mid x,2\mid y)\\ \gcd(x/2,y) & (2\mid x,2\nmid y)\\ \gcd(x,y/2) & (2\nmid x,2\mid y)\\ \gcd(x-y,y) & (2\nmid x,2\nmid y)(不妨设x>y) \end{cases} \]

    递归边界:两数相等 或者 一数为0 或者 一数为1 时都可以直接结束
    时间复杂度是 \(O(\log M)\)

    正常情况下因为常数比辗转相除法大,不会用到
    但这题恰好相反,乘以 2 、除以 2、减法三个操作对高精度都非常友好,所以这就是正解了

    洛谷P1890 gcd区间

    给定 \(n\) 个正整数 \(a_1,a_2,\cdots,a_n\)
    要回答 \(m\) 次询问,每次查询 \(\gcd(a_l,\cdots,a_r)\) 的值。

    \(1\le n\le 10^3,1\le m\le 10^6,1\le w\le 10^9\)\(w\) 表示 \(a_i\) 的大小)

    \(n\) 很小所以可以随便做
    但复杂度分析还是值得一提的

    大概是根据取模减半来分析的,我不大会,,直接挂链接了
    OI wiki 上的详细证明

    解法一:预处理所有区间 gcd 。时间复杂度 \(\Theta(n^2+m)\)
    解法二:线段树。时间复杂度 \(\Theta(n\log w+m(\log n+\log w))\)
    解法三:ST 表。时间复杂度 \(\Theta(n(\log n+\log w)+m\log w)\)

    洛谷P5435 基于值域预处理的快速 GCD

    给定两个数列 \(\{a_n\},\{b_n\}\),对每组 \((i,j)\) 求出 \(\gcd(a_i,b_j)\)
    \(\forall i\in [1,n]\),输出 \(A_i=\sum_{j=1}^ni^j\gcd(a_i,b_j)\),对 \(998244353\) 取模。

    \(1\le n\le 5000,1\le w\le 10^6\)\(w\) 表示 \(a_i,b_i\) 的大小)

    这个 \(A_i\) 其实没啥性质,它真的只是为了减少输出量(
    事实上确实存在 \(\Theta(w)\) 预处理,\(\Theta(1)\) 查询的做法

    核心思想是把一个数 \(x\) 分解为三个数的乘积,使其中每个数要么不超过 \(\sqrt x\),要么是质数
    对于 \(\sqrt x\) 以内数求 gcd 的问题,我们预处理打个 \(\sqrt w\times \sqrt w\) 的表就行了,时间复杂度 \(O(w)\)
    质数的情况也非常好算

    重点在于怎么分解
    对于一个数 \(x\) ,我们先找出 \(x\) 的最小质因子 \(p\),对 \(\frac xp\) 进行分解,再将 \(p\) 乘到分解出的最小数中
    \(\frac xp=abc(a\le b\le c)\),则 \(a\le \sqrt[3]{\frac xp}\) ,易证 \(p\le \sqrt[4]x\)\(pa\le \sqrt x\),符合要求
    \(p>\sqrt[4]w\),显然 \(x\) 至多有三个质因子,上述算法会找到它的质因数分解(可能会分解出多余的 1 ),总之没有问题
    实现时写个线性筛即可

    exGCD

    扩展欧几里得算法 (exgcd) 可以求出形如 \(ax+by=\gcd(a,b)(a,b\in\Z)\) 的二元一次不定方程的整数解。

    不妨设 \(a>b\)

    • \(b=0\)

      此时 \(x=1,y=0\) 即为一组解,直接返回即可

    • \(b>0\)

      考虑辗转相除,先求 \(bx+(a\%b)y=\gcd(b,a\%b)\) 的整数解。
      从同余的角度看,也许能转化得到 \(ax+by=\gcd(a,b)\) 的整数解。尝试一下,设

      \[ax_0+by_0=\gcd(a,b) \]

      \[bx_1+(a\%b)y_1=\gcd(b,a\%b) \]

      注意到 \(\gcd(a,b)=\gcd(b,a\%b),a\%b=a-(a/b)\times b\) ,故

      \[\begin{aligned}ax_0+by_0 &=bx_1+[a-(a/b)\times b]y_1 \\ &= ay_1 + b(x_1-(a/b)\times y_1)\end{aligned}\]

      故令 \(x_0=y_1,y_0=x_1-(a/b)\times y_1\) 即可。

    实现方式与欧几里得算法类似。

    int exgcd(int a,int b,int &x,int &y) { // 这里返回值为 gcd(a,b),写成 void 亦可
    	if (!b) { x=1,y=0; return a; }
    	int t=exgcd(b,a%b,y,x); y-=a/b*x; return t;
    }
    

    exgcd 的运行过程中始终有 \(|x|\le a,|y|\le b\),不需要担心爆 int 。(归纳即可证明)

    洛谷P5656 【模板】二元一次不定方程 (exgcd)

    给定正整数 \(a,b,c\),求 \(ax+by=c\) 的整数解。共 \(T\) 组数据。
    若方程无整数解,输出 -1
    若方程有整数解但无正整数解,输出所有整数解中 \(x\) 的最小正值、\(y\) 的最小正值;
    若方程有正整数解,输出正整数解的数量,以及正整数解中的 \(x_{\min},x_{\max},y_{\min},y_{\max}\)
    \(1\le T\le 2\times10^5,1\le a,b,c\le 10^9\)

    首先,方程有整数解的充要条件是 \(\gcd(a,b)\mid c\)
    必要性证明:\(\gcd(a,b)\mid ax+by,ax+by=c\Longrightarrow \gcd(a,b)\mid c\)
    充分性证明:exgcd 可以求出 \(ax+by=\gcd(a,b)\) 的一组整数解,将其按比例扩大即可得到 \(ax+by=c\) 的一组整数解。

    但是这还不够,题目实际上要我们求出通解

    \(a'=\frac a{\gcd(a,b)},b'=\frac b{\gcd(a,b)}\),则通解为

    \[\begin{cases}x=x_0+b'k\\y=y_0-a'k\end{cases} \]

    其中 \(x_0,y_0\)\(ax+by=c\) 的一组整数解,\(k\in\Z\)
    其实就等价于 \(a(x-x_0)+b(y-y_0)=0\)。证明和感性理解都不难

    还有些细节不说了 不是重点

    洛谷P4549 【模板】裴蜀定理

    给定整数序列 \(A_1,A_2,\cdots,A_n\),另有一待定整数序列 \(X_1,X_2,\cdots,X_n\)
    \(S=\sum\limits_{i=1}^nA_iX_i\),试求 \(S\) 的最小正值。
    \(1\le n\le 20,|A_i|\le 10^5\)\(A_i\) 不全为 \(0\)

    之前我们证明了方程 \(ax+by=c\) 有整数解的充要条件是 \(\gcd(a,b)\mid c\),这就是裴蜀定理,对应本题中 \(n=2\) 的情况。
    然而数据范围是 \(1\le n\le 20\),我们需要用到该定理的推广形式。
    先给出结论:设 \(g=\gcd(A_1,A_2,\cdots,A_n)\),则 \(S\) 的取值范围是 \(g\) 的所有倍数,最小正值即为 \(|g|\)

    证明可以用数学归纳法。设 \(n=k\) 时结论成立,我们要证 \(n=k+1\) 时也成立。
    \(g\mid S\) 是显然的,主要是证明对任意 \(g\) 的倍数 \(S\) 都有 \(X_1,X_2,\cdots,X_n\) 满足方程。

    由裴蜀定理,方程 \(\gcd(A_1,A_2,\cdots,A_k)X'+A_nX_n=S\) 必有整数解。
    只需求 \(X_1,X_2,\cdots,X_k\),使 \(A_1X_1+A_2X_2+\cdots+A_kX_k=\gcd(A_1,A_2,\cdots,A_k)X'\)
    \(n=k\) 的情形。由归纳假设,一定存在整数解。
    \(n=k+1\) 时结论成立。

    于是原结论得证。并且容易发现,对给定的 \(A_1,A_2,\cdots,A_n,S\),可通过 exgcd 求出一组整数解 \(X_1,X_2,\cdots,X_n\)
    当然题目中没有要我们求解,所以直接输出 \(|\gcd(A_1,A_2,\cdots,A_k)|\) 即可

  • 相关阅读:
    jquery手写实现单页滚动导航
    小程序:商品分类,实现滑块视图
    微信小程序增加悬浮在线客服
    小程序 杂记
    自动售货机 扫描支付 原理
    HTTP的SSL 证书安装
    表达
    Linux 下svn恢复到某一版本
    倒车入库 技巧
    svn 杂记
  • 原文地址:https://www.cnblogs.com/REKonib/p/15870840.html
Copyright © 2020-2023  润新知