博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数论3:线性同余方程组
阅读量:7209 次
发布时间:2019-06-29

本文共 3126 字,大约阅读时间需要 10 分钟。

欧几里得算法

又称辗转相处法,用以求两个数的最大公约数,引入符号\((a,b)\)表示a、b的最大公约数,\(a|b\)表示a能整除b,\(a\not |\ \ b\)表示a不能整除b。

现要证明\((a,b) = (b,a \mod b)\)

即证\(a = bq + r\)\((a,b)=(b,r)\)
\((a,b) = d_1\)\((b,r) = d_2\)
\(d_1(a^, - b^,q) = r\),即\(d_1 | r\)
其已知\(d_1 | b\),所以\(d_1 | (b,r)\),即\(d_1 | d_2\)
同理有\(d_2 | d_1\),所以得\(d_1 = d_2\)

因为\((n, 0) = n\),所以这也是欧几里得算法的出口。

时间复杂度\(O(\lg \max(a,b))\),因为每次迭代数字的大小至少减少一半。

int gcdr(int a, int b){    if(b == 0) return a;    return gcd(b, a%b);}int gcd(int a, int b){    while(b) {        int r = a % b;        a = b, b = r;    }    return a;}

扩展欧几里得算法

用以求不定方程\(ax + by = (a,b)\)的一组特解,为方便令\((a,b) = d\),引入符号\(\lfloor \frac a b \rfloor\)表示下取整,讨论其解法。

\(b=0\)时,特解\(x=1, y=0\)

\(b\neq 0\),令\(r=a \mod b\)考虑方程
\[by_1 + rx_1 = (b, r)\]
因为\((a,b)=(b,r)\),所以
\[ax + by = by_1 + rx_1\]
\(r = a \mod b = a - \lfloor \frac a b \rfloor b\),所以
\[ax + by = by_1 + (a - \lfloor \frac a b \rfloor b)x_1\]
整理得
\[ax + by = ax_1 + b(y_1 - \lfloor \frac a b \rfloor x_1)\]
得递归解
\[x = x_1 \qquad y = y_1 - \lfloor \frac a b \rfloor x_1\]
现一组特解为\(x_0, y_0\),则通解为
\[ x = x_0-bt \quad y = y_0 + at\]

时间复杂度同样为\(O(\lg\max(a,b))\),因为递归的执行次数的决定因素和欧几里得算法一样。

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

扩展欧几里得算法求\(ax + by = c\)

可以通过\(ax_0 + by_0 = d\)的特解放大倍数求得。

\(d \not |\ \ c\),则无解;
\(d \ \ \, |\ \ c\),则无解有以下讨论:
两边同时乘\(\frac c d\),可有
\[a\frac {x_0 c}{d} + b \frac {y_0c}{d} = c\]
特解为
\[x_1 = \frac {x_0 c}{d} \quad y_1 = \frac {y_0c}{d}\]
通解为
\[ x = x_1-\frac b d t \quad y = y_1 + \frac a d t\]

// 有解返回true,否则falsebool solve1(int a, int b, int c, int &x, int &y){    int d = exgcd(a, b, x, y);    if(c % d != 0) return 0;    int t = c / d;    x *= t, y *= t;    return 1;}

扩展欧几里得算法求\(ax \equiv b \pmod m\)

\(a \equiv b \pmod m\),a、b同余代表除m时余数相同,即\(a - \lfloor \frac a m \rfloor m = b - \lfloor \frac b m \rfloor m\),整理得

\[ mk = a-b,即m | (a-b) (k为整数)\]
所以上述同余方程可写为:
\[ax - my = b\]
这就可以用扩展欧几里得算法求\(ax + by = c\)方法求解了。

// 有解返回true,否则falsebool solve2(int a, int b, int m, int &x){    int y;    return solve1(a, -m, b, x, y);}

线性同余方程组\(a_ix \equiv b_i \pmod{m_i}\)

我们无法做到一次求解多个方程,那么考虑如何将其化为单一方程求解。

我们的目标是\(x = b \pmod m\),即b和m。

为方便解决,引入方程\(x \equiv 0 \pmod 1\),现只需要考虑以下两个方程的合并问题

\[ \begin{cases} x &\equiv b_0 & \pmod {m_0} \quad &①\\ a_1x &\equiv b_1 & \pmod {m_1} \quad &② \end{cases} \]

由①得到

\[x=b_0 + m_0u \quad ③\]

代入②得

\[a_1m_0u \equiv b_1 - a_1b_0 \pmod {m_1}\]

仅当\(d=(a_1m_0, m_1) | (b_1 - a_1b_0)\)时,整个方程组有解。

通过扩展欧几里得算法求\(ax \equiv b \pmod m\)的方法求得解\(u = u_0 \pmod {\frac {m_1}{d}}\),带回③得,\(x = b_0 + m_0u_0 + \frac {m_0m_1}{d}t\),即
\[x \equiv b_0 + m_0u_0 \pmod {\frac {m_0m_1}{(a_1m_0, m_1)}}\]

至此合并完成。

int n, A[maxn], B[maxn], M[maxn];// 有解返回true,否则falsebool solve_equ_set(int &b0, int &m0){    int u0;    b0 = 0, m0 = 1;    for(int i = 0; i < n; ++i) {        int na = A[i] * m0;        int nb = B[i] - A[i]*b0;        int d = gcd(na, M[i]);        if(!solve2(na, nb, M[i], u0)) return 0;        b0 += m0 * u0;        m0 *= M[i] / d;        b0 %= m0;    }    return 1;}

转载于:https://www.cnblogs.com/sequix/p/8524773.html

你可能感兴趣的文章
新IT运维模式下,全栈溯源助你解应用性能监控难题
查看>>
云存储标准应运而生
查看>>
物联网创新领域的三大驱动性趋势
查看>>
X光扫描揭示芯片密码卡入侵手段
查看>>
如何重新定义云数据中心的资源利用率
查看>>
一个PHP压缩类,在线压缩文件
查看>>
中国5G研发试验喜迎“小学课本”
查看>>
JavaScript依赖注入的实现思路
查看>>
防数据泄密:是否应实施“多重认证”?
查看>>
关于PHP的错误机制总结
查看>>
美国网络司令部133支网络部队已拥有初步作战能力
查看>>
如何看待阿里云加入Linux基金会金牌会员?
查看>>
三大应用需求:5G信道编码技术取得突破
查看>>
实例解读:如何减少Docker中的Java内存消耗
查看>>
测试JavaScript函数的性能
查看>>
TP-Link发布网格路由器Deco M5
查看>>
JP摩根预测:诺基亚2017年净利润将达14.21亿美元
查看>>
CDN行业“三足鼎立”格局已定,谁能代表未来?
查看>>
只“存活”9个月:Ubuntu 15.10今日停止支持
查看>>
淘汰Hyper-V replication 拥抱Storage Replica
查看>>