欧几里得算法:

  • 详见最大公因数gcd 和 最小公倍数lcm

扩展欧几里得算法:

  • 对于不完全为 0 的非负整数 a和b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
1
2
3
4
5
6
7
8
9
10
11
12
13
private static int extend_getGCD(int a, int b, int x, int y) {
int temp,ans;
if (b == 0) {
x = 1;
y = 0;
return a;
}
ans = extend_getGCD(b, a%b, x, y);
temp = x;
x = y;
y = temp - a / b * y;
return ans;
}

中国剩余定理

  • 也就是 给你一组同余方程,并保证两两互质 求最小的满足方程的非负整数 X
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.util.Scanner;
/**
* @author kid1999
* @title: P1495
* @date 2019/11/12 20:33
*/
public class P1495 {
public static void main(String[] args) {
// 输入数据
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long nums[] = new long[n+1];
long mod[] = new long[n+1];
for (int i = 0; i <n ; i++) {
nums[i] = sc.nextInt();
mod[i] = sc.nextInt();
}
// 用 同余的 加法 性质 统计出 sum(ai)
// 其中 ai = 除i以外的num相加 得lcm_num 再用lcm_num*n mod num[i] == mod[i]
long res = 0;
for (int i = 0; i <n ; i++) {
long lcm_num = 1;
for (int j = 0; j <n ; j++) {
if(j == i) continue;
lcm_num = lcm(lcm_num,nums[j]);
}
int k = 1;
while (true){
if(lcm_num*k % nums[i] == mod[i]){
res += lcm_num*k;
break;
}
k++;
}
}
// 计算出 最小公倍数
long stander = 1;
for (int i = 0; i <n ; i++) {
stander = lcm(stander,nums[i]);
}
// 逼近最小的 结果
while (res - stander >= 0){
res -= stander;
}
System.out.println(res);
}
public static long gcd(long a,long b){
return a == 0 ? b : gcd(b%a, a);
}
public static long lcm(long a,long b){
return (a*b)/gcd(a,b);
}
}

相关资料:

同余线性方程组

欧几里得算法扩展

来着油管的中国剩余定理讲解