逆元
扩展欧几里得
void exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得
{
if(b==0) {x=1;y=0;return;}
exgcd(b,a%b,y,x);
y-=x*(a/b);
return;
}
ll inv(ll a, ll n)//求a在模n下的逆元
{
ll x,y;
exgcd(a,n,x,y);
x = (x%n+n)%n;
return x;
}
把a/b变成a*x,x为b的逆元;
费马小定理
ll power(ll a, ll x) {
ll ans = 1;
while(x) {
if(x&1) ans = (ans * a) %mod;
a = (a * a) %mod;
x >>= 1;
}
return ans;
}
ll inv(ll a) {
return power(a, mod - 2);
}
例题 : hdu1576
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <cmath>
6 using namespace std;
7
8 #define mem(a) memset(a,0,sizeof(a))
9 #define ll long long
10
11 void exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得
12 {
13 if(b==0) {x=1;y=0;return;}
14 exgcd(b,a%b,y,x);
15 y-=x*(a/b);
16 return;
17 }
18
19 ll inv(ll a, ll n)//求a在模n下的逆元
20 {
21 ll x,y;
22 exgcd(a,n,x,y);
23 x = (x%n+n)%n;
24 return x;
25 }
26
27 int main()
28 {
29 int t;
30 ll a,b,n=9973;
31 scanf("%d",&t);
32 while(t--)
33 {
34 scanf("%lld%lld",&a,&b);
35 b = inv(b,n);
36 ll ans = (a*b)%n;
37 printf("%lld\n",ans);
38 }
39 return 0;
40 }