模运算是指取模运算,即求m/n的余数
例如:
7 mod 3 ≡ 1 ——-> 7 / 3 = 2 ……1
交换律
(a + b) mod m ≡ (b + a) mod m
(a * b) mod m ≡ (b * a) mod m
结合律
[(a + b) mod m + c] mod m ≡ [(a + (b + c) mod m) mod m]
[(a * b) mod m * c] mod m ≡ [(b * c) mod m * a] mod m
分配律
[(a + b) mod m * c] mod m ≡ [(a * c) mod m + (b * c) mod m] mod m
(a + b) mod m ≡ (a mod m + b mod m) mod m
(a - b) mod m ≡ (a mod m - b mod m) mod m
(a * b) mod m ≡ (a mod m * b mod m) mod m
a^b mod m ≡ (a mod m)^b mod m
模运算律
a ≡ c mod m
b ≡ d mod m
a + b ≡ (c + d) mod m
a - b ≡ (c - d) mod m
a * b ≡ (c * d) mod m
a / b ≡ (c / d) mod m
费马定理
如果p是素数,a为正整数且不能被p整除
a^(p-1) mod p = 1 mod p
(a^p * a^-1 * a) mod p = (1 * a) mod p
a^p mod p = a mod p
欧拉定理
对于素数p
ϕ(p) = p - 1
对于素数p^t
ϕ(p^t) = p^(t) - p^(t-1)
例如:
90 = 2 * 3^2 * 5
ϕ(90) = ϕ(2) * ϕ(3^2) * ϕ(5)
= (2-1) * (3^2 - 3^1) * (5 - 1)
= 24
如果 m>1 a与互素
a^ϕ(m) ≡ 1 mod m
例如:
m = 11
a = 2
(2,11) = 1
ϕ(11) = 10
2^10 ≡ 1 mod 11
Fermat大定理
当 n > 2 时
x^n + y^n = z^n(没有正整数解)
欧几里得算法
欧几里得算法又称为辗转相除法,是为了计算两个数的最大公约数。
定理:gcd(a,b) = gcd(b,a mod b) (a > b)
证明:
假设 a>b
a = k * b + r ------> r = a - k * b -----> r = a mod b
对于充分性:
假设d 为 a,b 的一个公约数,即d = gcd(a,b)
则 a | d, b | d (a与b都能被d整除)
r = a - k * b ----> r | d 即 d = gcd(b,r)
对于必要性:
假设 d 是 gcd(b,a mod b) 的公约数 ----> b | d , r | d
因为 a = k * b + r 则 a | d ----> d = gcd(d,b)
由上得知 gcd(a,b) 与 gcd(b,a mod b)公约数相等,所以最大公约数也相等
辗转相除到最后,gcd(x,0) = x
欧几里得算法c语言代码
int gcd(int a, int b)
{
if(b == 0)
return a;
return gcd(b, a % b);
}
int gcd(int a,int b)
{
int r;
while(b!=0)
{
r=a%b;//当a<b时第一个循环交换他们顺序
a=b;
b=r;
}
return a;
}
模幂运算
31^52 mod 33
ϕ(33) = ϕ(3 * 11) = ϕ(3) * ϕ(11)
= (3-1) * (11-1)
= 20
53 = 20 * 2 + 12
31^53 mod 33 = 31^12 mod 33
模平方计算
31^1 mod 33 ≡ 31
31^2 mod 33 ≡ 4
31^4 mod 33 ≡ 16
31^8 mod 33 ≡ 25
31^12 mod 33 ≡ ((31^4 * 31^8) mod 33) mod 33
≡ (16 * 25) mod 33 ≡ 4
扩展欧几里得求逆元
若 mx ≡ 1 mod n, 则称m关于1模n的乘法逆元为x。也可表示为mx ≡ 1 (mod n)。逆元相当于数论中的倒数。
条件:
只有当gcd(m,n) = 1时,m 才有关于 模n 的逆元。
方法一:
利用费马小定理
a * a^(p-2) ≡ 1 mod p
a^(p-2)即为a关于1模p的逆元,但只能求出p为素数的情况下的乘法逆元
方法二:
采用扩展欧几里德算法来计算普遍情况下的乘法逆元
由 mx ≡ 1 mod n
推出
mx -kn = 1
a * x mod b = 1
ax + by = gcd(a,b) = 1
令a=m,b=n
所求出x即为逆元
加上x = (x mod t + t) mod t 即为最小逆元
为什么可以用扩展欧几里得求得逆元?
因为ax ≡ 1 (mod p) 就是ax-yp = 1.
把y写成+的形式就是ax + py = 1,为方便理解下面我们把p写成b就是ax + by = 1。
ax = 1 - by -----> ax = 1 mod b
by = 1 - ax -----> by = 1 mod a
就表示x是a的模b乘法逆元,y是b的模a乘法逆元。然后就可以用扩展欧几里得定理求值
欧几里得c语言代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,p;
int exgcd (ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int r=exgcd (b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-a/b*y;
return r;
}
int main()
{
scanf ("%d%d",&n,&p);
for (int i=1;i<=n;i++)
{
ll x,y;
exgcd (i,p,x,y);
x=(x+p)%p;
printf ("%d\n",x);
}
return 0;
}