a
x
≡
1
(
m
o
d
m
)
ax \equiv 1( \bmod m)
ax≡1(modm)
若
a
a
a与
m
m
m互质,那么
x
x
x则为
a
a
a的逆元
可推得式子:
a
x
+
m
y
=
1
ax + my = 1
ax+my=1
利用扩展欧几里得求:
#include <bits/stdc++.h>
using namespace std;
int exgcd(int a, int b, int &x, int &y)
{
if(!b) {
x = 1;
y = 0;
return a;
}
int x1, y1, Gcd;
Gcd = exgcd(b, a % b, x1, y1);
x = y1;
y = x1 - a / b * y1;
return Gcd;
}
const int mod = 19940417;
int main()
{
int inv2, y;
exgcd(2, mod, inv2, y);
cout << "inv2: " << (inv2%mod+mod)%mod << "\ny: " << -y;
}
例题
读完题,这不就是求逆元嘛
注意开long long
code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int exgcd(int a, int b, int &x, int &y)
{
if(!b) {
x = 1, y = 0;
return a;
}
int x1, y1, Gcd;
Gcd = exgcd(b, a % b, x1, y1);
x = y1;
y = x1 - a / b * y1;
return Gcd;
}
signed main()
{
int a, b;
cin >> a >> b;
int inv, y;
exgcd(a, b, inv, y);
cout << (inv % b + b) % b << endl;
}
例题二
题意:
求 A B A^B AB的约数之和
Sol:
约数之和
一个数为
N
N
N:
p
1
k
1
∗
p
2
k
2
∗
⋅
⋅
⋅
∗
p
n
k
n
p_1^{k_1} * p_2^{k_2} * ··· * p_n^{k_n}
p1k1∗p2k2∗⋅⋅⋅∗pnkn
约数个数:
∏
i
=
1
n
(
1
+
k
i
)
\prod_{i=1}^{n}(1 + k_i)
∏i=1n(1+ki)
约数之和:
∏
i
=
1
n
∑
j
=
0
k
i
(
p
j
)
\prod_{i=1}^{n} \sum_{j=0}^{k_i}(p^j)
∏i=1n∑j=0ki(pj)
分治法求 s u m ( p , k ) sum(p, k) sum(p,k):
p
0
+
p
1
+
p
2
+
⋅
⋅
⋅
+
p
k
p^0 + p^1 + p^2 + ··· + p^k
p0+p1+p2+⋅⋅⋅+pk
=
(
p
0
+
p
1
+
⋅
⋅
⋅
+
p
k
2
)
+
p
k
2
+
1
∗
(
p
0
+
p
1
+
⋅
⋅
⋅
+
p
k
2
)
(p^0 + p^1 + ··· + p^{\frac{k}{2}})+ p^{\frac{k}{2} + 1} * (p^0 + p^1 + ··· + p^{\frac{k}{2}})
(p0+p1+⋅⋅⋅+p2k)+p2k+1∗(p0+p1+⋅⋅⋅+p2k)
=
(
1
+
p
k
2
+
1
)
∗
s
u
m
(
p
,
k
/
2
)
(1 + p^{\frac{k}{2} + 1}) * sum(p, k / 2)
(1+p2k+1)∗sum(p,k/2)
Code1:
#include <bits/stdc++.h>
using namespace std;
const int mod = 9901;
int qpow(int a, int b)
{
a %= mod;
int ans = 1;
while(b){
if(b&1) ans = ans * a % mod;
b>>=1; a = a * a % mod;
}
return ans;
}
int sum(int p, int k)
{
if(k==0) return 1;
if(k % 2 == 0) return (p % mod * sum(p, k - 1) + 1) % mod;
return (1 + qpow(p, k / 2 + 1))% mod * sum(p, k / 2) % mod;
}
int main()
{
int A, B; cin >> A >> B;
int res = 1;
for(int i = 2; i <= A ; ++i)
{
int s = 0;
while( A % i == 0) s ++, A /= i;
if(s) res = res * sum(i, s * B) % mod;
}
if(!A) res = 0;
cout << res << endl;
}
公式法:
我们发现:
p
0
+
p
1
+
p
2
+
⋅
⋅
⋅
+
p
k
p^0 + p^1 + p^2 + ··· + p^k
p0+p1+p2+⋅⋅⋅+pk 就是一个等比数列求前n项和。
结果为:
p
i
k
i
∗
B
+
1
−
1
p
i
−
1
\frac{p_i^{k_i * B + 1} - 1}{p_i - 1}
pi−1piki∗B+1−1
我们可以用快速幂求出分子,分母的逆元(存在的话)
根据费马小定理:
若p是质数,则对于任意整数a,有 a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv 1(\bmod p) ap−1≡1(modp)
所以:当模数p为质数的时候, b p − 2 b^{p-2} bp−2即为 b b b的乘法逆元
特别的,如果不存在逆元,即
p
[
i
]
−
1
p[i] - 1
p[i]−1是9901的倍数,此时乘法逆元不存在
但是
p
i
m
o
d
9901
=
1
p_i \bmod 9901 = 1
pimod9901=1
所以:
1
+
p
i
+
p
i
2
+
⋅
⋅
⋅
+
p
i
B
∗
c
i
+
1
≡
1
+
1
+
1
2
+
⋅
⋅
⋅
+
1
B
∗
c
i
+
1
≡
B
∗
c
i
+
1
(
m
o
d
9901
)
1 + p_i + p_i^2 + ··· + p_i^{B * c_i + 1} \equiv 1 + 1 + 1^2 + ··· + 1^{B * c_i + 1} \equiv B * c_i + 1 (\bmod 9901)
1+pi+pi2+⋅⋅⋅+piB∗ci+1≡1+1+12+⋅⋅⋅+1B∗ci+1≡B∗ci+1(mod9901)
Code2:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a, b, m, ans = 1, mod = 9901;
int p[20], c[20];
void divide(int n)
{
m = 0;
for(int i = 2; i <= n / i; ++i)
{
if(n % i == 0)
{
p[++ m] = i;
c[m] = 0;
while(n % i == 0) ++ c[m], n /= i;
}
}
if(n > 1) p[ ++ m] = n, c[m] = 1;
}
int qpow(int a, int b, int p)
{
int ans = 1;
while(b)
{
if(b & 1) ans = ans * a % p;
a = a * a % p;
b >>= 1;
}
return ans;
}
signed main()
{
cin >> a >> b;
divide(a);
for(int i = 1; i <= m; ++i)
{
if((p[i] - 1) % mod == 0) {
ans = (b * c[i] + 1 ) % mod * ans % mod;
continue;
}
int x = qpow(p[i], b * c[i] + 1, mod);
x = (x - 1 + mod) % mod;
int y = p[i] - 1;
y = qpow(y, mod - 2, mod);
ans = ans * x % mod * y % mod;
}
if(!a) ans = 0;
cout << ans % mod << endl;
}