一、思路:
(A/B)%9937 = A*B-1 %9973. 这里的B-1 代表乘法逆元,而不是1/B.
乘法逆元:A除以一个数模P,等于A乘以这个数的乘法逆元模P。
所以我们只需要求解出B对于9973的乘法逆元B-1即可。
-
解法一:费马小定理求解乘法逆元
若a是一个整数,b是一个质数,那么 ab ≡ a(mod b) 或 ab-1≡1 (mod b)
由扩展欧几里得可以得出:
因为gcd(a,b) == 1, ax ≡ 1(mod b) x是乘法逆元
ab-1 = a*ab-2= ax ≡1(mod b). 所以 x = ab-2 就是乘法逆元。 我们可以通过快速幂求解。
在本题求x = a9973-2。 -
解法二:扩展欧几里得
因为gcd(B,9973) == 1,所以 Bx ≡ 1(mod 9973) x 是 B-1,也就是B的乘法逆元
通过ex_gcd(B,9973)求出来的x就是B-1,x可能是负数所以要处理一下。
static int x, y;
static int ex_gcd(int a, int b) {
if (b == 0) {
x = 1;y = 0;
return a;
}
int ans = ex_gcd(b, a % b);
int tem = y;
y = x - a / b * y;
x = tem;
return ans;
}
二、代码:
import java.util.Scanner;
public class HDU_1576 {
static int n, b;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
n = sc.nextInt();
b = sc.nextInt();
//System.out.println(f1(b, 9973) * n % 9973);
System.out.println(f2(b, 9973) * n % 9973);
}
}
static int x, y;
static int ex_gcd(int a, int b) {
if (b == 0) {
x = 1;y = 0;
return a;
}
int ans = ex_gcd(b, a % b);
int tem = y;
y = x - a / b * y;
x = tem;
return ans;
}
//1.通过扩展欧几里得求解乘法逆元
static int f1(int a, int b) {
int d = ex_gcd(a, b);
int t = b / d;
//因为求出来的x可能是负数 利用通解所以处理一下
x = (x % t + t) % t;
return x;
}
//2.通过费马小定理求解乘法逆元
static long f2(long a,long b) {
//a * a^(b-2) x = a^(b-2)
b = b - 2;
long ans = 1;
while (b != 0) {
if ((b & 1) == 1) {
ans = (ans * a) % 9973;
}
a = (a * a) % 9973;
b /= 2;
}
return ans;
}
}