首页 > 代码库 > K - A/B(逆元)

K - A/B(逆元)

Description

要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
 

Input

数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
 

Output

对应每组数据输出(A/B)%9973。
 

Sample Input

2 1000 53 87 123456789
 

Sample Output

7922 6060



解题思路:

这道题应该用拓展欧几里德算法,总的思路是 (N = 9973):(A/B)%N = ( (A%N) * (1/B)%N)%N
因为 gcd(B,N) = 1,所以 = (n * (gcd(B,N)/B)%N)%
又因为根据拓展欧几里德算法可以得到一组x,y,使得gcd(B,N) = B*x + N*y,代入上式就可以得到
(n * (x + N*y/B)%N)%N= ((n%N) * (x + N*y/B)%N)%N= (n*(x+N*y/B))%N
因为y < B,所以y/B = 0所以原式G= (n*x)%N
又因为x可能为负,所以只要G = (G%N+N)%N,就可以化成正的了。



代码如下:

#include<stdio.h>
#include <iostream>
using namespace std;
int exgcd(int a,int b,int &x,int &y)
{
    int r;
    int t;
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    r=exgcd(b,a%b,x,y);
    t=x;
    x=y;
    y=t-a/b*y;
    return r;
}
int main()
{
    int T,n,b,x,y;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&b);
        exgcd(b,9973,x,y);
        x*=n;
        x=(x%9973+9973)%9973;
        printf("%d\n",x%9973);
    }
    return 0;
}