1. 程式人生 > >【同余方程組】POJ1006 生理周期

【同余方程組】POJ1006 生理周期

inverse 題目 更新 sub 同余 cas amp -- turn

同余方程組:

  先來看一道題目:有物不知其數,三三數之剩二;五五數之剩三;七七數之剩二。問物幾何? 然後我們可以做如下變換,設x為所求的數。

   x%3=2 x = a1(%m1) ①
   x%5=3 ===> x = a2(%m2) ②
   x%7=2 x = a3(%m3)

  根據前面兩式可以得到

    x = a1+m1y1 (1)
   x = a2+m2y2

  兩式相減得到 m1y1 - m2y2 = a2 - a1 這是一個線性不定方程,可解出y1 ---> linearEquation(m1

,-m2,a2-a1) 帶回(1),得特解x0 = a1+m1*y1 --> 得到通解表達式 x =x0 + k*lcm(m1,m2) 得一個新方程 x = x0 (mod lcm(m1,m2))

  代碼:

/**
 * 
 * @param a 余數組成的數組
 * @param m 模組成的數組
 * @return
 * @throws Exception
 */
public static long linearEquationGroup(Long[] a, Long[] m) throws Exception {
  int len = a.length;
  
if (len == 0 && a[0] == 0) return m[0]; for (int i = 1; i < len; i++) { // 這裏往前看是兩個方程 long a2_a1 = a[i] - a[i - 1]; long d = linearEquation(m[i - 1], -m[i], a2_a1); // 現在的x是y1,用y1求得一個特解 long x0 = a[i - 1] + m[i - 1] * x; long lcm = m[i - 1] * m[i] / d; a[i]
= (x0 % lcm + lcm) % lcm;// x0變成正數 m[i] = lcm; } // 合並完之後,只有一個方程 : x = a[len-1] (% m[len-1]) //long d = linearEquation(1, m[len-1], a[len-1]); return a[len - 1] % m[len - 1]; }

題目:POJ1006 生理周期

  技術分享圖片

  技術分享圖片

  代碼:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 import java.util.Scanner;
 4 
 5 public class POJ1006 {
 6 
 7     public static void main(String[] args) throws Exception {
 8         Scanner scanner = new Scanner(System.in);
 9         int t = 1;
10         List<Long[]> aList = new ArrayList<Long[]>();
11         List<Long> dList = new ArrayList<Long>();
12         while(scanner.hasNext()){
13             Long []a = {scanner.nextLong(),scanner.nextLong(),scanner.nextLong()};
14             Long d = scanner.nextLong();
15             if (a[0]==-1&&a[1]==-1&&a[2]==-1&&d==-1) {
16                 break;
17             }else {
18                 aList.add(a);
19                 dList.add(d);
20             }
21         }
22         for (int i = 0; i < aList.size(); i++) {
23             Long[] a = aList.get(i);
24             long d = dList.get(i);
25             Long[] m = { (long) 23, (long) 28, (long) 33 };
26             long res = MyGcd.linearEquationGroup(a, m);
27             while (res <= d) {
28                 res += 21252;
29             }
30             System.out.println("Case " + (t++) + ": the next triple peak occurs in " + (res - d) + " days.");
31         }
32     }
33     
34     private static class MyGcd {
35         static long x;
36         static long y;
37 
38         /**
39          * 
40          * @param a 余數組成的數組
41          * @param m 模組成的數組
42          * @return
43          * @throws Exception
44          */
45         public static long linearEquationGroup(Long[] a, Long[] m) throws Exception {
46             int len = a.length;
47             if (len == 0 && a[0] == 0)
48                 return m[0];
49 
50             for (int i = 1; i < len; i++) {
51                 // 這裏往前看是兩個方程
52                 long a2_a1 = a[i] - a[i - 1];
53                 long d = linearEquation(m[i - 1], -m[i], a2_a1);
54                 // 現在的x是y1,用y1求得一個特解
55                 long x0 = a[i - 1] + m[i - 1] * x;
56                 long lcm = m[i - 1] * m[i] / d;
57                 a[i] = (x0 % lcm + lcm) % lcm;// x0變成正數
58                 m[i] = lcm;
59             }
60             // 合並完之後,只有一個方程 : x = a[len-1] (% m[len-1])
61             //long d = linearEquation(1, m[len-1], a[len-1]);
62             return a[len - 1] % m[len - 1];
63         }
64 
65         public static long inverseElement(long a, long mo) throws Exception {
66 
67             long d = linearEquation(a, mo, 1);
68             x = (x % mo + mo) % mo;
69             return d;
70         }
71 
72         public static long linearEquation(long a, long b, long m) throws Exception {
73             long d = ext_gcd(a, b);
74             // m不是gcd(a,b)的倍數,這個方程無解
75             if (m % d != 0)
76                 throw new Exception("無解");
77             long n = m / d;// 約一下,考慮m是d的倍數
78             x *= n;
79             y *= n;
80             return d;
81         }
82 
83         public static long ext_gcd(long a, long b) {
84 
85             if (b == 0) {
86                 x = 1;
87                 y = 0;
88                 return a;
89             }
90             long res = ext_gcd(b, a % b);
91             long x1 = x;// 備份x
92             x = y;// 更新x
93             y = x1 - a / b * y;// 更新y
94             return res;
95         }
96 
97     }
98 
99 }

  結果:

    技術分享圖片



【同余方程組】POJ1006 生理周期