HDU1576(逆元+扩展欧几里得求逆元)

要求(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
/*
本题是扩展欧几里得求逆元还有同余定理的应用,
同余定理的公式:(a+b)%mod=(a%mod+b%mod)%mod    
				(a*b)%mod=(a%mod*b%mod)%mod
扩展欧几里得也有自己的一个公式:a*x+b*y=gcd(a,b),如果要求逆元的话
则需要满足a*x+b*y=1(x是a的逆元),因为逆元要满足一个公式 (a*x)%mod=1,就称x是a关于
mod的逆元,切(y/a)%mod= (y*x)%mod
扩展欧几里得简略推理过程:
:a*x1+b*y1=gcd(a,b),b*x2+(a%b)*y2=gcd(b,a%b)
 \ 由辗转相除法可得到 gcd(a,b)=gcd(b,a%b) 
 \ 从而得到a*x1+b*y1=b*x2+(a%b)*y2 
 \ 即a*x1+b*y1=b*x2+(a-(a/b)*b)*y2
 \ =a*y2+b*(x2-(a/b)*y2) 
 \ 所以 x1=y2,y1=x2-(a/b)*y2.
 采用递归思想,当b=0时停止递归,此时x=1,y=0;回溯后会 得到一组关于二元一次方程的解
*/
#include 
using namespace std;
typedef long long ll;
void exgcd(ll a,ll b,ll &x,ll &y)    //x,y有取地址符号,所以可以在主函数直接用 
//该函数还可以同时求出a,b的最大公约数,在终止是返回a,非终止返回函数的返回值即可 
{
	if(b==0) //递归停止,开始往回计算x的值 
	{
		x=1;
		y=0;
		return ;
	}
	exgcd(b,a%b,x,y);  //递归 
	ll t=y;
	y=x-(a/b)*y;
	x=t;    //如果要求a,b的最大公约数,返回函数的返回值 
}
int main()
{
	ll x,y,a,b=9973,n;
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>a;
		exgcd(a,b,x,y);
		while(x<0)  //防止x<0 
		{
			x+=b;
		}
		x%=9973;
		cout<<(n*x)%9973<

 

你可能感兴趣的:(ACM)