也叫”孙子定理”

中国剩余定理.pdf

例题

204. 表达整数的奇怪方式

给定 2n 个整数 a1,a2,…,an 和 m1,m2,…,mn,求一个最小的非负整数 x,满足 ∀i∈[1,n],x≡mi(mod ai)。
输入格式
第 1 行包含整数 n。
第 2…n+1行:每 i+1行包含两个整数 ai 和 mi,数之间用空格隔开。
输出格式
输出最小非负整数 x,如果 x 不存在,则输出 −1。
如果存在 x,则数据保证 x 一定在 64 位整数范围内。
数据范围
1≤ai≤231−1
0≤mi1≤n≤25
输入样例:

  1. 2
  2. 8 7
  3. 11 9

输出样例:

  1. 31

思路:
不是严格意思上的中国剩余定理,因为题目没有说任意 mi, mj 两两互质
所以可能有解,也可能无解,需要一步一步算
每次合并两个同余式并判断是否有解,有解则继续计算,否则退出计算
表达整式的奇怪方式.pdf

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner sc = new Scanner(System.in);
  5. int n = sc.nextInt();
  6. long a1, m1;
  7. a1 = sc.nextLong();
  8. m1 = sc.nextLong();
  9. //解的标识
  10. boolean flag = true;
  11. long x = 0;
  12. for (int i = 0; i < n - 1; i++) {
  13. long a2, m2;
  14. a2 = sc.nextInt();
  15. m2 = sc.nextInt();
  16. long[] k1 = new long[1], k2 = new long[1];
  17. long d = exgcd(a1, a2, k1, k2);
  18. //是否有解的判断
  19. if ((m2 - m1) % d != 0) {
  20. flag = false;
  21. x = -1;
  22. break;
  23. }
  24. //有解
  25. long t = (m2 - m1) / d;
  26. //求系数解
  27. k1[0] *= t;
  28. //求系数的最小非负整数特解
  29. k1[0] = (k1[0] % (a2/d) + (a2/d)) % (a2/d);
  30. //求当前x的特解
  31. x = k1[0] * a1 + m1;
  32. //求x的通解系数,方便下一轮迭代
  33. m1 = x;
  34. a1 = Math.abs(a1 / d * a2);
  35. }
  36. System.out.println(x);
  37. }
  38. static long exgcd(long a, long b, long[] x, long[] y) {
  39. if (b == 0) {
  40. x[0] = 1;
  41. y[0] = 0;
  42. return a;
  43. }
  44. long d = exgcd(b, a % b, y, x);
  45. y[0] -= a / b * x[0];
  46. return d;
  47. }
  48. }