扩展欧几里得 HDU 1576
题意;要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
因为:A%9973=n;
所以:9973*y+n=A:
设:A/B=x;(可以整除)
所以:9973*y+n=B*x;
所以:B*x-9973*y=n; ①式
又因为:gcd(B,9973) = 1;
所以必存在 x1*B+9973*y1=1;②式
②式*n=①式
所以只要求出x1,就可以得到x,又因为x=a/b,只要在 mod 9973就是答案了。
现在给出扩展欧几里得:
对于gcd(a,b) = d,对(a, b)用欧几里德辗转相除会最终得到(d, 0)。此时对于把a =d, b = 0 代入a*x + b*y = d,显然x = 1,y可以为任意值。 我们可以用a = d, b = 0的情况逆推出来任何gcd(a, b) = d 满足a*x + b*y = d的解。如果x0,y0是b*x + (a%b)*y = d 的解,那么对于a*x + b*y = d的解呢?
b*x + (a%b)*y = d → b*x + (a - [a/b]*b)*y = d → a*y + b*(x - [a/b]*y) = d 所以a*x + b*y = d的解 x1 = y0,y1= x0 - [a/b]*y0;
我们可以地推出a*x+b*y=gcd(a,b),中的下,x和y.现在所有问题就解决了。
#include<stdio.h>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
void ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return ;
}
ex_gcd(b,a%b,x,y);
ll temp=x;
x=y;
y=temp-a/b*y;
return ;
}
int main()
{
ll t,a,b,n,x,y;
cin>>t;
while (t--)
{
cin>>n>>b;
int ans;
ex_gcd(b,9973,x,y);
x=x*n;
ans=(x%9973+9973)%9973;//(a + b) % p = (a % p + b % p) % p,所以(x%9973+9973)%9973=x%9973,若x是负数,x%9973会出错,所以化 成(x%9973+9973)%9973,先使x变正再 mod 9973
cout<<ans<<endl;
}
return 0;
}
cout<<ans<<endl;
}
return 0;
}