拓展欧几里得

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 #define ll long long
 9 
10 const int INF = 1e9;
11 const ll MOD = 19940417;
12 
13 //裴蜀定理:若 ax + by = n 有解,则 gcd(a, b) | n
14 //拓展欧几里得:求 ax + by = gcd(a, b) 的解,通过辗转相除法得到一组特解:x0 y0
15 // 得到 ax + by = c 的特解:
16 // x = x0 * c / gcd(a, b)
17 // y = y0 * c / gcd(a, b)
18 // 通解:
19 // X = x + b / gcd(a, b) * t
20 // Y = y - a / gcd(a, b) * t   (t = 0, 1, 2, 3 ...)
21 //最小非零解: x = (x % b + b) % b
22 // ax + by = gcd(a, b)
23 // ax + by + k * ab - k * ak = gcd(a, b)
24 // a(x + kb) + b(y - bk) = gcd(a, b)  ---->  x = (x % b + b) % b
25 
26 ll exgcd(ll a, ll b, ll &x, ll &y)
27 {
28 
29     if(b == 0){//推理1,终止条件
30         x = 1;
31         y = 0;
32         return a;
33     }
34     ll r = exgcd(b, a%b, x, y);
35     //先得到更底层的x2,y2,再根据计算好的x2,y2计算x1,y1。
36     //推理2,递推关系
37     ll t = y;
38     y = x - (a/b) * y;
39     x = t;
40     return r;
41 }
42 
43 void solve()
44 {
45 
46     //ax同余1(mod prime)  求最小正整数解
47     // ax + by = n ---> ax' + by' = gcd(a, b)
48     // k = gcd(a, b)  k*(ax' + by') = n
49     //以下 a, b, x, y对应上面 a, b, x', y'
50     ll a, b, x, y;
51     //以下求出mod不为质数的逆元
52     // a / b % mod c
53     // a / b * b^-1 ≡ x * b^-1(mod c)
54     // b * b^-1 ≡ 1 (mod c)
55     // b * b^-1 + y * c  = 1
56     // a * x + b * y = 1
57     exgcd(2, MOD, x, y);
58     ll inv2 = x;
59     exgcd(6, MOD, x, y);
60     ll inv6 = x;
61 
62     cout << "inv2 = " << (inv2 + MOD) % MOD << endl;
63 
64     cout << "inv6 = " << (inv6 + MOD) % MOD << endl;
65 }
66 
67 int main()
68 {
69 
70     solve();
71 
72     return 0;
73 }

 

posted @ 2020-06-12 11:11  SummerMingQAQ  阅读(190)  评论(0编辑  收藏  举报