第六章 數學問題 -------- 6.10 特殊的同餘方程—逆元

Curtis_發表於2019-03-22

逆元:

  同餘方程 ax≡1(mod n),gcd(a,n) = 1 時有解,這時稱求出的 x 為 a 的對模n的乘法逆元。(注意:如果gcd(a,n)如果不等於1則無解),解法還是利用擴充套件歐幾里得演算法求解方程 ax + ny = 1 求出 x。

/**
     * 求逆元
     * ax = 1 (% mo),gcd(a,mo)=1
     * ax+mo*y=1
     * */
    public static long inverseElement(long a, long mo) throws Exception {

      long d = linearEquation(a, mo, 1);//ax+mo*y=1
      x = (x % mo + mo) % mo;//保證x>0
      return d;
    }

題目:HDU-1576

  思路:

       設(A/B)%9973 = k, 則A/B = k + 9973x  (x未知), 因此A = kB + 9973xB,又A%9973 = n, 所以kB%9973 = n,  故kB = n + 9973y (y未知),故(k/n)B +(-y/n)*9973 = gcd(B,9973) = 1擴充套件歐幾里得 求出k/n,  再乘以個n,記得取模,就是answer了。

  程式碼:

import java.util.Scanner;

/**
 * (A/B)%9973,求餘,除法不滿足交換性,可改為求B關於9973的逆元x,
 * 這樣結果等價於Ax%9973等價於x*A%9973等價於xn%9973,
 */

public class HDU1576 {
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int T = scanner.nextInt();
        for (int i = 0; i < T; i++) {
            int n = scanner.nextInt();
            int b = scanner.nextInt();
            try {
                MyGcd.inverseElement(b, 9973);
                long x = MyGcd.x;
                System.out.println(x*n%9973);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    }

    private static class MyGcd{
        static long x;
        static long y;

        public static long gcd(long m, long n) {
            return n == 0 ? m : gcd(n, m % n);
        }

        public static long ext_gcd(long a,long b){
            if (b==0) { 
                x = 1;
                y = 0;
                return a;
            }
            long res = ext_gcd(b, a % b);
            long x1 = x;
            x = y;
            y = x1 - a / b * y;
            return res;
        }

        public static long linearEquation(long a, long b, long m) throws Exception {
            long d = ext_gcd(a, b);
            if (m % d != 0) {
                throw new Exception("無解");
            }
            long n = m / d;
            x *= n;
            y *= n;
            return d;
        }
        
        public static long inverseElement(long a, long mo) throws Exception {

            long d = linearEquation(a, mo, 1);// ax+mo*y=1
            x = (x % mo + mo) % mo;// 保證x>0
            return d;
        }
    }
}

  結果:

 

 

相關文章