算法——数论——同余

目录

同余

一、试题 算法训练 同余方程


同余

  • 同余使人们能够用等式的形式简洁地描述整除关系
  • 同余:若 m(正整数),a 和 b 是整数,a%m==b%m,或(a-b)%m==0,记为  b(mod m)
  • 求解一元线性同余方程等价于求解二元线性丢番图方程  
    • 一元线性同余方程 ax\equiv b(mod m),解法看下面第一题
    • 二元线性丢番图方程 ax+my=b
  • 逆:ax\equiv 1(mod m)的一个解为 a 模 m 的逆

一、试题 算法训练 同余方程

问题描述

  求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解。

输入格式

  输入只有一行,包含两个正整数ab,用一个空格隔开。

输出格式

  输出只有一行,包含一个正整数x0,即最小正整数解。输入数据保证一定有解。

样例输入

3 10

样例输出

7

数据规模和约定

  对于40%的数据,2 ≤b≤ 1,000;
  对于60%的数据,2 ≤b≤ 50,000,000;
  对于100%的数据,2 ≤ab≤ 2,000,000,000。

 

 分析:

  • 这行代码 (x % b + b) % b 的目的是确保最终的结果落在 0 到 b-1 的范围内,即取余操作的结果始终为非负数。

    首先,我们知道 % 运算符返回的结果可能是负数,具体取决于被除数和除数的正负性。为了保证结果始终为非负数,我们首先对 x 求模 b,得到一个值在 -b+1 到 b-1 之间的数。然后,我们加上 b,这样就可以确保结果大于等于 0 且小于 2b。最后再次对 b 取模,使结果落在 0 到 b-1 的范围内。

    这样的处理方式可以确保得到正确的最小正整数解,同时保证结果在合理的范围内。

package no1_1;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long a = scanner.nextInt();
        long b = scanner.nextInt();
        System.out.println(modInverse(a, b));
    }
    //求a模b的逆,即为同余方程的一个解
    public static long modInverse(long a, long b) {//求逆
        long[] result = new long[2];
        extendGcd(a, b, result);//扩展欧几里得算法求ax+by=1的一个特解result[0]
        long x = result[0];
        return (x % b + b) % b;//保证返回最小正整数
    }

    
    public static long extendGcd(long a, long b, long[] result) {
        if (b == 0) {
            result[0] = 1;
            result[1] = 0;
            return a;
        }
        long[] temp = new long[2];
        long d = extendGcd(b, a % b, temp);
        result[0] = temp[1];
        result[1] = temp[0] - a / b * temp[1];
        return d;
    }
}

 

 

你可能感兴趣的:(数据结构与算法(java版),算法)