- 相关题目链接:
- 题目相关内容:数论之exgcd以及线性递推求逆元。
exgcd
基本模型,形如ax+by=c的方程,要是方程有整数解,我们可得c=gcd(a,b),我们可以用exgcd求出其最小整数解,我们已知a,b,当b=0是,显然得a=1,我们考虑一下gcd的过程,加入当前我们已求得bx2+a%by2=gcd(a,b)的解为x2,y2,那如何得出x1,y1呢?具体证明过程请见下图
exgcd的时间复杂度与gcd类似,最坏情况下为θ(nlogn)exgcd求逆元
逆元:求关于x的同余方程 ax≡1(mod b) 的最小正整数解,x即为a的逆元。
根据裴蜀定理,要使同余方程ax≡1(mod b)有解,要满足gcd(a,p)|b,由题意得,b=1,所以gcd(a,p)=1
我们再来分析一下这个同余方程
所以,我们可以通过exgcd来解这个方程,同时这也求出了a的逆元。代码(T1 AC)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using namespace std;
ll sc() {
ll xx = 0, ff = 1; char cch = gc;
while (cch < '0' || cch > '9') {
if (cch == '-') ff = -1; cch = gc;
}
while (cch >= '0'&& cch <= '9') {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
ll n, m;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1;
y = 0;
return a;
}
ll gcd = exgcd(b, a % b, x, y);
ll x2 = x, y2 = y;
x = y2;
y = x2 - a / b * y2;
return gcd;
}
int main() {
ll x = 0, y = 0;
n = sc(); m = sc();
exgcd(n, m, x, y);
printf("%lld\n", (x + m) % m);
return 0;
}代码(T2 80Pts)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using namespace std;
ll sc() {
ll xx = 0, ff = 1; char cch = gc;
while (cch < '0' || cch > '9') {
if (cch == '-') ff = -1; cch = gc;
}
while (cch >= '0'&& cch <= '9') {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
ll n, m;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1;
y = 0;
return a;
}
ll gcd = exgcd(b, a % b, x, y);
ll x2 = x, y2 = y;
x = y2;
y = x2 - a / b * y2;
return gcd;
}
int main() {
ll x = 0, y = 0;
n = sc(); m = sc();
for(int i = 1; i <= n; i++) {
x = 0, y = 0;
exgcd(i, m, x, y);
printf("%lld\n", (x + m) % m);
}
return 0;
}线性递推求逆元
首先,我们声明在下列计算中同余均是在mod p意义下
我们可以简单计算1^(-1)≡1
考虑任意正整数i,假定i-1的逆元已经正确计算,我们递推方程的计算过程如下:
- 代码(T2 AC)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using namespace std;
ll sc() {
ll xx = 0, ff = 1; char cch = gc;
while (cch < '0' || cch > '9') {
if (cch == '-') ff = -1; cch = gc;
}
while (cch >= '0'&& cch <= '9') {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
ll n, m;
ll f[Maxn];
int main() {
n = sc(); m = sc();
f[1] = 1;
for(int i = 2; i <= n; i++)
f[i] = (m - m / i) * f[m % i] % m;
for(int i = 1; i <= n; i++)
printf("%lld\n", f[i]);
return 0;
}