首页 > 技术文章 > 取模运算的性质、扩展欧几里德定理

fzuhyj 2017-12-11 00:38 原文

取模运算

对于整型数a,b来说,取模运算或者求余运算的方法都是:

1.求 整数商: c = a/b;

2.计算模或者余数: r = a - c*b.

求模运算和求余运算在第一步不同: 取余运算在取c的值时,向0 方向舍入(fix()函数);而取模运算在计算c的值时,向负无穷方向舍入(floor()函数)。

 

例如:计算-7 Mod 4

那么:a = -7;b = 4;

第一步:求整数商c,如进行求模运算c = -2(向负无穷方向舍入),求余c = -1(向0方向舍入);

第二步:计算模和余数的公式相同,但因c的值不同,求模时r = 1,求余时r = -3。

归纳:当a和b符号一致时,求模运算和求余运算所得的c的值一致,因此结果一致。

当符号不一致时,结果不一样。求模运算结果的符号和b一致,求余运算结果的符号和a一致。比如上式:-7取模4=1 -7取余4=-3

基本性质 

(1)若p|(a-b),则a≡b (% p) 即  a%p = b % p。例如 11 ≡ 4 (% 7), 18 ≡ 4(% 7)   //  | 表示整除

(2)(a % p)=(b % p)意味a≡b (% p)  

(3)对称性:a≡b (% p)等价于b≡a (% p)   

(4)传递性:若a≡b (% p)且b≡c (% p) ,则a≡c (% p)   

运算规则

模运算与基本四则运算有些相似,但是除法例外。其规则如下:   

(a + b) % p = (a % p + b % p) % p (1)   

(a - b) % p = (a % p - b % p) % p (2)   

(a * b) % p = (a % p * b % p) % p (3)   

ab % p = ((a % p)b) % p (4)   

结合率:

 ((a+b) % p + c) % p = (a + (b+c) % p) % p (5)   

((a*b) % p * c)% p = (a * (b*c) % p) % p (6)  

 

交换率: (a + b) % p = (b+a) % p (7)   

(a * b) % p = (b * a) % p (8)   

分配率: ((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (9) 

  

重要定理

若a≡b (% p),则对于任意的c,都有(a + c) ≡ (b + c) (%p);(10)   

若a≡b (% p),则对于任意的c,都有(a * c) ≡ (b * c) (%p);(11)   

若a≡b (% p),c≡d (% p),则 (a + c) ≡ (b + d) (%p),(a - c) ≡ (b - d) (%p),   (a * c) ≡ (b * d) (%p),(a / c) ≡ (b / d) (%p); (12)   

若a≡b (% p),则对于任意的c,都有ac≡ bc (%p); (13)

 

 

 

问题: 扩展欧几里德算法求解线性同余方程

对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数。那么存在唯一的整

数 x,y 使得 gcd(a,b)=ax+by。

 

一、递归

设 a>b。

1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

2,ab<>0 时

设 ax1+by1=gcd(a,b);

bx2+(a mod b)y2=gcd(b,a mod b);

根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);

则:ax1+by1=bx2+(a mod b)y2;

即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;

根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;

这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.

上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以

结束。

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

 

推荐阅读