- 欧几里得算法
对任意整数a, b 并且 b不等于0, 有 gcd(a, b) = gcd(b, a % b)
代码
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
朴素写法
int gcd(int a, int b){
if(b == 0) return a;
return gcd(b, a % b);
}
- 欧几里得扩展式
对于任意整数a, b, 存在一对整数x, y, 满足ax + by =gcd(a, b), 程序求出方程的一组特解, x*, y*, 并且返回a, b的最大公约数 d。
代码
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, x, y);
int z = x;
x = y;
y = z - y * (a / b);
return d;
}
- 欧拉函数
在学习欧拉函数之前我们学习互质的定义: 对两个正整数a, b ,若gcd(a, b) = 1, 则称a, b互质。
欧拉函数:1 - N 中与 N 互质的数的个数被称为欧拉函数,记为 φ(N), 在算术基本定理中, N = p1 ^ c1 * p2 ^ c2 …*pm ^ cm, 则可以把欧拉函数记做:
φ(N) = N * (p1 - 1) / p1 * (p2 - 1) / p2 * … *(pm - 1) / pm
欧拉函数有两个性质:
- 对于任意 n > 1, 在1 - n 中与 n 互质的数的和为 n * φ(n) / 2
- 若 a, b 互质, 则φ(a*b) = φ(a) * φ(b)
- 积性函数
如果 a, b 互质时有:f(a*b) = f(a) * f(b), 那么称 f 为积性函数 - 若 f 是积性函数, 且在算术基本定理中 n = p1 ^ c1 * p2 ^ c2 * … * pm^cm, 则有 f(n) = f(p1 ^ c1) * f(p2 ^ c2) * … * f(pm ^ cm)
代码
int p(int n){
int ans = n;
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0){
ans = ans / i * (i - 1); // φ(N)
while(n % i == 0) n /= i; //把i这个质因数去掉
}
}
if(n > 1) ans = ans / n * (n - 1);
return ans;
}
- 欧拉筛选
利用Eratosthenes筛法求出欧拉函数 p[n] 存的 n 的欧拉函数
代码
int p[1010];
void g(int n){ //欧拉筛选
for(int i = 2; i <= n; i++)
p[i] = i;
for(int i = 2; i <= n; i++){
if(p[i] == i){
for(int j = i; j <= n; j += i){
p[j] = p[j] / i * (i - 1);
}
}
}
}
- 费马小定理
若 p 是质数, 则对于任意整数 a , 有 a^p ≡ a (mod p), 即是 a^p 与 a 同余
- 欧拉定理
若正整数 a, n 互质, 则 a^φ(n) ≡ 1 (mod n), 即是 a^φ(n) % n = 1
- 欧拉定理的推论
1. 若正整数 a, n 互质, 则对于任意的正整数 b, 有 a^b ≡ a ^(b mod φ(n)) (mod n)
2. 当 a, n 不一定互质且 b > φ(m) 时,有a^b ≡ a^(b mod φ(n) + φ(n)) (mod n)。
许多计数类的题目要求我们把答案对一个质数 p 取模后输出。面对a+b,a-b,a*b 这样的算式,可以在计算前先把a,b对p取模。面对乘方算式,根据欧拉定理的推论,可以先把底数对p取模、指数对φ( p ) 取模,再计算乘方。
- 线性同余方程
已知a, b, m, 求x, 满足方程 a * x ≡ b (mod m) 我们称它为线性同余方程
a * x ≡ b( mod m)等价于 a * x - b 是 m 的倍数,不妨设为 -y 倍。于是,该方程可以改写为 a * x + m * y = b。 方程有解的当且仅当gcd(a, m) | b.
同余方程练习题:NOIP2012/CH3301 同余方程
题目描述
求关于x的同余方程 ax ≡ 1(mod b) 的最小正整数解。
输入格式
输入只有一行,包含两个正整数a,b,用一个空格隔开。
输出格式
输出只有一行,包含一个正整数x,表示最小正整数解。
输入数据保证一定有解。
数据范围
2≤a,b≤2∗109
输入样例:
3 10
输出样例:
7
代码
#include<iostream>
using namespace std;
typedef long long ll;
ll a, b, x, y;
ll exgcd(ll a, ll b, ll &x, ll &y){
if(b == 0){
x = 1;
y = 0;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll z = x;
x = y;
y = z - y * (a / b);
return d;
}
int main(){
cin >> a >> b;
cout << exgcd(a, b, x, y) << endl;
return 0;
}
- 中国剩余定理
设 m1 , m2,… mn 是两两互质的整数,m = m1 * m2 * … * mn,Mi = m / mi, ti 是线性同余方程 Mi * ti ≡ 1 (mod mi) 的一个解。对于任意的n个整数a1,a2,…,an, 方程组
x ≡ a1 (mod m1)
x ≡ a2( mod m2)
…
x ≡ = an ( mod mn)
有整数解,解为x = (a1 * M1* t1) + (a2 * M2* t2) + …+ (an * Mn* tn)。