模运算规则
基本运算法则
- 加法运算法则: (a+b)%c=(a%c+b%c)%c
- 减法运算法则: (a−b)%c=(a%c−b%c)%c
- 乘法运算法则: (a∗b)%c=(a%c∗b%c)%c
- 指数运算法则: (ab)%c=((a%c)b)%c
- 除法运算法则:需要求逆元,我们后面讲
交换律
- 加法交换律: (a+b)%c=(b+a)%c
- 乘法交换律: (a∗b)%c=(b∗a)%c
结合律
-加法结合律:
((a+b)%d+c)%d(a+(b+c)%d)%d=(((a+b)%d)%d+c%d)%d=((a+b)%d+c%d)%d=(a+b+c)%d=(a%d+((b+c)%d)%d)%d=(a%d+(b+c)%d)%d=(a+b+c)%d
-乘法结合律:
((a∗b)%d∗c)%d(a+(b+c)%d)%d=(((a∗b)%d)%d∗c%d)%d=((a∗b)%d∗c%d)%d=(a∗b∗c)%d=(a%d∗((b∗c)%d)%d)%d=(a%d∗(b∗c)%d)%d=(a∗b∗c)%d
分配率
((a+b)%d∗c)%d=((a+b)%d%d∗c%d)%d=((a+b)%d∗c%d)%d=((a+b)∗c)%d=(a∗c+b∗c)%d=((a∗c)%d+(b∗c)%d)%d
同余运算
定义
两个整数
a
,
同余运算法则
- 加法法则 : a≡b(modp)⇔(a+c)≡(b+c)(modp)
- 乘法法则 : a≡b(modp)⇔(a∗c)≡(b∗c)(modp)
- 混合法则:如果
a≡b(modp)
并且
c≡d(modp)
,那么可以得出如下几条结论:
- (a+c)≡(b+d)(modp)
- (a∗c)≡(b∗d)(modp)
- (a−c)≡(b−d)(modp)
模运算应用
求最大公约数 gcd(a,b)
1. 更相减损法
这个算法最早记载于中国的数学名著《九章算术》中,其主要的思路:假设 x=gcd(a,b) , 显然我们知道 a%x=0 和 b%x=0 , 根据同余运算法则 (a−b)%x==0 . 假设 gcd(a,b) 是方程组的解
{a%xb%x=0=0
显而易见, gcd(a,a−b) 也是方程组的解
{a%x(a−b)%x=0=0
我们可以推出如下结论: gcd(a,b)=gcd(a,a−b) . 于是我们找到了求最大公约数的解法。
int jiuzhang_gcd(int a, int b) {
while (a != b) {
if (a > b) {
a -= b;
} else {
b -= a;
}
}
return a;
}
2. 辗转相除法
辗转相除法又叫Euclidean 算法,是著名数学家欧几里得发明的,其基本的思想是,假设我们要求的是整数
a
和
很容易得出如下结论:
r=a−cb=mx−cnx=Cx
所以,gcd(a,b) = gcd(a%b, b).
int euclidean_gcd(int a, int b) {
while (max(a,b) % min(a,b) != 0) {
if (a > b) {
a %= b;
} else {
b %= a;
}
}
return min(a,b);
}
3. 扩展辗转相除法
问题描述:假定存在两个互素的正整数
a
和
思想:由于
a
和
{a′b′=b=a%b
并求解下面方程的解:
a′x′+b′y=gcd(a′,b′)⇔bx′+(a−(a/b)b)y′=gcd(a,b)⇔ay′+b(x′−(a/b)y′)=gcd(a,b)
只要我们求出上述方程的解(x’,y’), 经过转换我们就可以求出原始方程的解(x,y), 转换的方程如下
{xy=y′=x′−(a/b)y′
经过迭代,最终会出现求解 1∗x+0∗y=gcd(1,0) 的情况,这正是这个解法的终止条件。
void ext_gcd(int a, int b, int &x, int &y) {
if (b != 0) {
int xx, yy;;
ext_gcd(b, a%b, xx, yy);
x = yy;
y = xx - (a / b) * yy;
} else {
x = 1;
y = 0;
}
}