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)。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
Output
对应每组数据输出(A/B)%9973。
已经给出了Amod9973,我们只需要求B^-1mod9973就行,这里的B^-1就是需要求的模9973的乘法逆元,这里给出定义:
对于整数a、p,如果存在整数b,满足ab mod p =1,则说,b是a的模p乘法逆元。
定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1
直接用拓展欧几里得来求既可:一般情况下,ax+by=1;得 x为a mod b 的逆元,y为 b mod a的逆元。
再来看拓展欧几里得,是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d。
再根据gac(a,b)=gcd(b,a%b)来进行推导,根据边界条件b==0既可求出边界条件的x和y,再根据两组x,y的关系式可以得到其中的一组特解。
本题代码:
#include<stdio.h>
#include<algorithm>
using namespace std;
long long x,y;
void ex_GCD(long long a,long long b) //拓展欧几里得
{
if(b==0) //边界
{
y=0;
x=1; //x=gcd(a,b)
return ;
}
ex_GCD(b,a%b);
long long m=y; //关系式
long long n=x-a/b*y;
x=m;
y=n;
}
int main()
{
int t;
long long a,b,n;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&a);
b=9973;
ex_GCD(a,b);
long long ans=(n*x%b);
if(ans<0) //可能为负数
printf("%lld\n",ans+b);
else
printf("%lld\n",ans);
}
return 0;
}