📜  模方程解数的Java程序(1)

📅  最后修改于: 2023-12-03 15:40:37.830000             🧑  作者: Mango

模方程解数的Java程序

简介

模方程是指形如 $ax \equiv b \pmod{m}$ 的方程,其中 $a,b,m$ 都是整数,$\pmod{m}$ 表示模 $m$ 意义下的同余关系。模方程的解又称为同余方程的解。

本文介绍使用 Java 编写模方程解数的程序。该程序接受用户输入的 $a,b,m$ 三个参数,输出模方程的解,如果无解则输出 "无解"。

算法

模方程的解可以使用扩展欧几里得算法求解。具体来说,如果 $g=\gcd(a,m)$,则原方程等价于 $gx \equiv b \pmod{\frac{m}{g}}$。如果 $g$ 不整除 $b$,则原方程无解;否则可以使用扩展欧几里得算法求解 $gy+{\frac{m}{g}}z=1$ 的一组解 $(y_0,z_0)$,然后解得 $x_0 \equiv \frac{b}{g}y_0 \pmod{\frac{m}{g}}$。所有解形如 $x_0+k\frac{m}{g}$,$k\in\mathbb{Z}$。

代码

下面是使用 Java 语言编写的求解模方程的程序代码。用户输入 $a,b,m$ 三个参数,在控制台输出模方程的解或 "无解"。

import java.util.Scanner;

public class ModEquationSolver {
    
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("请输入模方程 ax ≡ b (mod m) 的参数 a,b,m:");
        long a = input.nextLong(), b = input.nextLong(), m = input.nextLong();
        long[] ans = solveModEquation(a, b, m);
        if (ans == null) {
            System.out.println("无解");
        } else {
            for (int i = 0; i < ans.length; i++) {
                System.out.print(ans[i]);
                if (i < ans.length - 1) {
                    System.out.print(", ");
                }
            }
            System.out.println();
        }
    }
    
    public static long[] solveModEquation(long a, long b, long m) {
        long g = gcd(a, m);
        if (b % g != 0) { // 异常情况
            return null;
        } else {
            long[] yz = exgcd(a, m);
            long x0 = b / g * yz[0] % (m / g); // 求得一个特解 x_0
            long[] ans = new long[(int) g]; // 共 g 个解
            for (int i = 0; i < g; i++) {
                ans[i] = x0 + i * (m / g);
            }
            return ans;
        }
    }
    
    // 扩展欧几里得算法
    public static long[] exgcd(long a, long b) {
        if (b == 0) {
            return new long[] {1, 0};
        } else {
            long[] yz = exgcd(b, a % b);
            return new long[] {yz[1], yz[0] - a / b * yz[1]};
        }
    }
    
    // 求最大公约数
    public static long gcd(long a, long b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
}
使用方法

在命令行窗口中执行以下命令:

javac ModEquationSolver.java
java ModEquationSolver

然后按照提示输入三个参数 $a,b,m$,回车后程序会输出模方程的解或 "无解"。输入多组数据时,只需要重复输入 $a,b,m$ 并按回车即可。

示例
输入
3 4 11
输出
9
解释

原方程为 $3x \equiv 4 \pmod{11}$,因为 $\gcd(3,11)=1$,所以可将我们的注意力放到如何求得 $3x \equiv 1 \pmod{11}$ 的解。由扩展欧几里得算法可得 $3\times4+11\times (-1)=1$,于是 $y_0=4,z_0=-1$,再带入$x_0 \equiv \frac{4}{1}=4 \pmod{\frac{11}{1}=11}$ 得出 $x_0=4$,因此这个特解为 $x=4$,因为 $\gcd(3,11)=1$,所以 $x$ 的解正好有 $1$ 个,即 $x=9$。

输入
12 57 42
输出
无解
解释

原方程为 $12x \equiv 57 \pmod{42}$,因为 $\gcd(12,42)=6$,所以可将原方程变形为 $2x\equiv 9\pmod3$。但是这等价于 $0 \equiv 1 \pmod3$,无解。