首先先了解一下扩展欧几里得算法(此部分是从acm之家转载而来)
扩展欧几里德算法是欧几里得算法的扩展。
已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。
用类似辗转相除法,求二元一次不定方程47x+30y=1的整数解。
- 47=30*1+17
- 30=17*1+13
- 17=13*1+4
- 13=4*3+1
然后把它们改写成“余数等于”的形式
- 17=47*1+30*(-1) //式1
- 13=30*1+17*(-1) //式2
- 4=17*1+13*(-1) //式3
- 1=13*1+4*(-3)
然后把它们“倒回去”
- 1=13*1+4*(-3) //应用式3
- 1=13*1+[17*1+13*(-1)]*(-3)
- 1=13*4+17*(-3) //应用式2
- 1=[30*1+17*(-1)]*4+17*(-3)
- 1=30*4+17*(-7) //应用式1
- 1=30*4+[47*1+30*(-1)]*(-7)
- 1=30*11+47*(-7)
得解x=-7, y=11。
基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
由题意可得, A=9973*y+n (2)又因为A必能被B整除
所以设A=B*x
代入(2)式,可得B*x-9973*y=n
所以用拓展欧几里得算法可解出B*x-9973*y=1=gcd(B,9973)的不定方程
两边同时乘n,x1=x*n,又因为x1可能为负数,所以可以这样转化x1=(x1%9973+9973)%9973
代码如下
#include<cstdio>
using namespace std;
const int MOD=9973;
void gcd(int a, int b, int &x, int &y)
{
if(!b)
{x = 1; y = 0;}
else
{gcd(b, a%b, y, x); y-=x*(a/b);}
}
int main()
{
int x, y, t, n, b;
scanf("%d",&t);
while(t--)
{
scanf("%d%d", &n, &b);
gcd(b, MOD, x, y);
x*=n;
printf("%d\n",(x%MOD+MOD)%MOD);
}
return 0;
}