中国剩余定理和欧几里得算法

首先重点讲解中国剩余定理,举例:
一个数x除d1余r1,除d2余r2,除d3余r3,那么,求这个数的最小值 。
解答:
r1,r2,r3一定是一个整数,一的倍数,所以可以使用到数论倒数的知识来解答,即逆元:
逆元:对于正整数a和m,如果有ax=1(mod m),那么把这个同余方程中x的最小正整数解叫做a模m的逆元。
比如2 * 3 % 5 = 1,那么3就是2关于5的逆元,或者说2和3关于5互为逆元。
那么在应用中,可以用到的是:逆元的使用规则,已知除以d1余r1,除d2余r2,除d3余r3,d1的数论倒数是M1,d2的数论倒数是M2,d3的数论倒数是M3,那么,x=M1✲r1+M2✲r2+M3✲r3。
由于可能得到的数比d1,d2,d3的公倍数要大,所以可以将得到的数减去公倍数,得到的就是这个数的最小值。

还可以不用数论倒数的方法来理解:
引入实例:一个整数除以三余一,除以五余二,除以七余三,求这个最小整数。

若一个数可以被5,7整除,但不可以被3整除,那么该数一定是5,7的倍数,5,7的最小公倍数:5*7=35,但是不能被3整除,且除3余1。
35%3=2,那么,可以(35✲a)%3=1,解之,a至少等于2:
5✲7✲2=70
依次类推,可以被3,5整除,除7余3,3✲5✲b%7=3,b=3,解为3✲5✲3=45。
可以被3,7整除,除5余2:3✲7✲c%5=2,c=2,解为:3✲7✲2=42。

5✲7✲2=70
3✲5✲3=45
3✲7✲2=42

题解为70+45+42=157,由于3,5,7的最小公倍数是105,那么:
157-105=52。

解答:被除数加上(或减去)除数的倍数,除数不变,余数也不变,那么,例如70为除3余1,而45,42都为3的倍数,那么,加上3的倍数以后除以3的结果仍然是余1的,依次类推,可得上式解。

在代码的实现过程中,考虑到程序的简洁性,通常使用的是第一个方法:求逆元解答,但是逆元需要如何求出呢?在这里使用的便是欧几里得算法。
欧几里得算法,又称辗转相除法,主要用来求解两个数的最大公约数:
可以使用递归迭代等方法,主要实现形式为:
gcd(a,b)=gcd(b,a%b)。

欧几里得算法的扩展算法主要应用于三个方面:
(1)求解不定方程;
(2)求解模线性方程(线性同余方程);
(3)求解模的逆元;

这里主要讲解欧几里得算法的扩展算法:
(1)使用扩展欧几里德算法解决不定方程的办法:

对于不定整数方程pa+qb=c,若 c mod Gcd(p, q)=0,则该方程存在整数解,否则不存在整数解。
上面已经列出找一个整数解的方法,在找到p ✲ a+q ✲ b = Gcd(p, q)的一组解p0,q0后,p ✲ a+q ✲ b = Gcd(p, q)的其他整数解满足:
p = p0 + b/Gcd(p, q) ✲ t
q = q0 - a/Gcd(p, q) ✲ t(其中t为任意整数)
至于pa+qb=c的整数解,只需将p ✲ a+q ✲ b = Gcd(p, q)的每个解乘上 c/Gcd(p, q) 即可。

在找到p ✲ a+q ✲ b = Gcd(a, b)的一组解p0,q0后,应该是得到p ✲ a+q ✲ b = c的一组解p1 = p0✲(c/Gcd(a,b)),q1 = q0✲(c/Gcd(a,b)),

p ✲ a+q ✲ b = c的其他整数解满足:
p = p1 + b/Gcd(a, b) ✲ t
q = q1 - a/Gcd(a, b) ✲ t(其中t为任意整数)
p 、q就是p ✲ a+q ✲ b = c的所有整数解。
相关证明可参考:http://www.cnblogs.com/void/archive/2011/04/18/2020357.html

用扩展欧几里得算法解不定方程ax+by=c;
代码如下:

01.bool linear_equation(int a,int b,int c,int &x,int &y)  
02.{  
03.    int d=exgcd(a,b,x,y);  
04.    if(c%d)  
05.        return false;  
06.    int k=c/d;  
07.    x*=k; y*=k;    //求得的只是其中一组解  
08.    return true;  
09.}  

(2)用扩展欧几里德算法求解模线性方程的方法:
同余方程 ax≡b (mod n)对于未知数 x 有解,当且仅当 gcd(a,n) | b。且方程有解时,方程有 gcd(a,n) 个解。
求解方程 ax≡b (mod n) 相当于求解方程 ax+ ny= b, (x, y为整数)

设 d= gcd(a,n),假如整数 x 和 y,满足 d= ax+ ny(用扩展欧几里德得出)。如果 d| b,则方程

a✲ x0+ n✲ y0= d, 方程两边乘以 b/ d,(因为 d|b,所以能够整除),得到 a✲ x0* b/ d+ n✲ y0✲ b/ d= b。
所以 x= x0✲ b/ d,y= y0✲ b/ d 为 ax+ ny= b 的一个解,所以 x= x0✲ b/ d 为 ax= b (mod n ) 的解。
ax≡b (mod n)的一个解为 x0= x✲ (b/ d ) mod n,且方程的 d 个解分别为 xi= (x0+ i✲ (n/ d ))mod n {i= 0... d-1}。

设ans=x✲(b/d),s=n/d;

方程ax≡b (mod n)的最小整数解为:(ans%s+s)%s;

相关证明:

证明方程有一解是: x0 = x'(b/d) mod n;
由 a✲x0 = a✲x'(b/d) (mod n)
a✲x0 = d (b/d) (mod n) (由于 ax' = d (mod n))
= b (mod n)

证明方程有d个解: xi = x0 + i✲(n/d) (mod n);
由 a*xi (mod n) = a ✲ (x0 + i✲(n/d)) (mod n)
= (a✲x0+a✲i✲(n/d)) (mod n)
= a ✲ x0 (mod n) (由于 d | a)
= b

首先看一个简单的例子:
5x=4(mod3)
解得x = 2,5,8,11,14.......由此可以发现一个规律,就是解的间隔是3.
那么这个解的间隔是怎么决定的呢?
如果可以设法找到第一个解,并且求出解之间的间隔,那么就可以求出模的线性方程的解集了.
我们设解之间的间隔为dx.
那么有a✲x = b(mod n);a✲(x+dx) = b(mod n);两式相减,得到:
a*dx(mod n)= 0;

也就是说a*dx就是a的倍数,同时也是n的倍数,即a✲dx是a 和 n的公倍数.为了求出dx,我们应该求出a 和 n的最小公倍数,此时对应的dx是最小的.

设a 和 n的最大公约数为d,那么a 和 n 的最小公倍数为(a*n)/d.
即a✲dx = a✲n/d;
所以dx = n/d.
因此解之间的间隔就求出来了.
代码如下:

01.bool modular_linear_equation(int a,int b,int n)
02.{  
03.    int x,y,x0,i;  
04.    int d=exgcd(a,n,x,y);  
05.    if(b%d)  
06.        return false;  
07.    x0=x*(b/d)%n;   //特解  
08.    for(i=1;i<d;i++)  
09.        printf("%d\n",(x0+i*(n/d))%n);  
10.    return true;  
11.}  

(3)用欧几里德算法求模的逆元:

同余方程ax≡b (mod n),如果 gcd(a,n)== 1,则方程只有唯一解。
在这种情况下,如果 b== 1,同余方程就是 ax=1 (mod n ),gcd(a,n)= 1。
这时称求出的 x 为 a 的对模 n 乘法的逆元。
对于同余方程 ax= 1(mod n ), gcd(ax,n)= 1 的求解,即ax减一是n的整数倍,假设为y倍,有ax=ny+1,由于y是一个未知量,故方程的求解就是解方程:ax+ ny= 1,x, y 为整数。这个可用扩展欧几里德算法求出,原同余方程的唯一解就是用扩展欧几里德算法得出的 x 。
如下代码,所求解为(ax)%b=1,求解为x的值:

#include <iostream>
#include <cstdio>
using namespace std;

int x,y,q;
void extend_Eulid(int a,int b)
 {
     if(b == 0){
          x = 1;y = 0;q = a;
     }else{
         extend_Eulid(b,a%b);
         int temp = x;
         x = y;
         y = temp - a/b*y;
     }
}
int main()
{
     int a,b;
     cin>>a>>b;
     extend_Eulid(a,b);
     printf("%d=(%d)*%d+(%d)*%d\n",q,x,a,y,b);
     return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容