【算法】扩展欧几里得与同余方程

  很久之前写的……有很多错误。现在赶紧更新一波……

  1.扩展欧几里得算法:求解不定方程 \(a * x + b * y = m\)。

   首先,当 \(m\) 为 \(gcd(a, b)\) 的倍数时,方程有整数解;否则无整数解。

   证明:首先如果不满足此条件,一定不会有整数解。此处显然无须赘述。若 \(p*x + q*y = gcd(p, q)\)  存在解,那么 \(a*x + b*y = c\) 存在解。因为可以将式子左右两边同除 \(gcd(a, b)\),那么此时有 \(a_{1} * x + b_{1} * y = c_{1}\)。而此时 \(gcd(a_{1}, b_{1}) = 1\)。所以在求得了 \(a_{1} * x + b_{1} * y = 1\) 之后,我们可以同时给方程的两边乘上 \(c _{1}\) 。

     所以问题转化为:如何证明 \(p * x + q * y = gcd(p, q)\) 存在解?两边同除 \(gcd(p, q)\) 得到 \(a * x + b * y = 1\)(\(gcd(a, b) = 1\))。

根据欧几里得算法我们有 \(gcd\left ( a,b \right ) = gcd\left ( b,a \ mod\  b \right )\)

我们若能求出 \(b * x' + \left ( a\ mod\ b \right ) * y' = gcd(a, b)\),

则:\(b * x' + \left ( a \ mod \ b \right ) * y'\)

\( = a * y' + b * \left ( x' - \left ( \frac{a}{b} \right )* y' \right )\)

\(=gcd\left ( a,b \right )\);

又因为\(gcd(a, b) = 1\),

所以得出:\(x = y', y = x' - \left ( \frac{a}{b} \right )* y'\);

   在代码实现上可以递归求解:

void exgcd(int a, int b, int &x, int &y)
{
    if(!b) { x = 1, y = 0; return; }
    exgcd(b, a % b, x, y);
    ll tem = x;
    x = y;
    y = tem - a / b * y;
}

    在我们获得了不定方程的一组解\(\left ( x_{0},y_{0} \right )\)之后,则不定方程的任何一组解满足 :\(\Delta x = \frac{m * b}{gcd\left ( a,b \right )}, \Delta y = \frac{m * a}{gcd\left ( a,b \right )}\)。

    扩展欧几里得算法一个非常常见的应用即为:求乘法逆元。

  2.同余方程:

    求解形如 \(a * x\equiv b \left ( mod \ m \right ) \) 的方程。其实我并不是很会同余方程,但有两个定理还是非常重要的:

若\(gcd\left ( a,b \right )=1\),则方程\(ax\equiv c \left ( mod\ b \right )\) 在 \(\left [ 0, b - 1 \right ]\)上有唯一解。

若\(gcd\left ( a,b \right )=d, d|c\),则方程\(ax\equiv c \left ( mod\ b \right )\) 在 \(\left [ 0, \frac{b}{d} - 1 \right ]\)上有唯一解。

    之前我是不会证明的,现在会了,感谢我Daddy的大力相助。在这里就截一下图(公式写起来好麻烦呀……)

    

    这两条性质让我们知道在求解模意义下的问题时(尤其是在卷积和反演中需要反复变化枚举对象时),可以转化为枚举模后的结果。例如\(nx \equiv  k \left ( \ mod\ m \right )\),\(k \in \left [ 0, m - 1 \right ]\)。则当\(x \in \left [ 0, q \right]\) 时,\(nx \ mod\ m = k\)  一共出现了\(\frac{q}{\frac{m}{d}}\) 次。

posted @ 2018-06-09 09:36  Twilight_Sx  阅读(712)  评论(0编辑  收藏  举报