整除、同余的概念及快速幂
整除、余数都是小学概念,但还是得学习一些细节。
整除
1、
a
∣
b
a|b
a ∣ b 代表b可以被a整除,b是a的倍数,a是b的约数。
2、约定0可以被任何数整除。
3、若存在整数
x
x
x ,
y
y
y 使得
a
∗
x
+
b
∗
y
=
1
a*x+b*y = 1
a ∗ x + b ∗ y = 1 ,且
a
∣
n
a|n
a ∣ n 、
b
∣
n
b|n
b ∣ n ,那么
(
a
∗
b
)
∣
n
(a*b)|n
( a ∗ b ) ∣ n
其他性质比较显然,就不作赘述。
同余
基本概念
若
a
,
b
a, b
a , b 两个自然数满足
m
∣
(
a
−
b
)
m|(a-b)
m ∣ ( a − b ) ,则说a和b关于m同余,记为
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m )
同余具有以下性质
1、自反性:
a
≡
a
(
m
o
d
m
)
a \equiv a(mod\ m)
a ≡ a ( m o d m )
2、对称性:若
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m ) ,则
b
≡
a
(
m
o
d
m
)
b \equiv a(mod\ m)
b ≡ a ( m o d m )
3、传递性:若
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m ) ,且
b
≡
c
(
m
o
d
m
)
b \equiv c(mod\ m)
b ≡ c ( m o d m ) ,则
a
≡
c
(
m
o
d
m
)
a \equiv c(mod\ m)
a ≡ c ( m o d m )
4、同加性:若
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m ) ,则
a
+
c
≡
b
+
c
(
m
o
d
m
)
a+c \equiv b+c(mod\ m)
a + c ≡ b + c ( m o d m )
5、同乘性:①若
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m ) ,则
a
∗
c
≡
b
∗
c
(
m
o
d
m
)
a*c \equiv b*c(mod\ m)
a ∗ c ≡ b ∗ c ( m o d m )
②若
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m ) 且
c
≡
d
(
m
o
d
m
)
c \equiv d(mod\ m)
c ≡ d ( m o d m ) ,则
a
∗
c
≡
b
∗
d
(
m
o
d
m
)
a*c \equiv b*d(mod\ m)
a ∗ c ≡ b ∗ d ( m o d m )
6、同幂性:若
a
≡
b
(
m
o
d
m
)
a \equiv b(mod\ m)
a ≡ b ( m o d m ) ,则
a
n
≡
b
n
(
m
o
d
m
)
a^n \equiv b^n(mod\ m)
a n ≡ b n ( m o d m )
7、推论1:
a
∗
b
m
o
d
k
=
(
a
m
o
d
k
)
∗
(
b
m
o
d
k
)
m
o
d
k
a*b\ mod\ k=(a\ mod\ k)*(b\ mod\ k)mod\ k
a ∗ b m o d k = ( a m o d k ) ∗ ( b m o d k ) m o d k ,指数取余重要原理。
8、推论2:若
a
m
o
d
p
=
x
a\ mod\ p=x
a m o d p = x ,
a
m
o
d
q
=
x
a\ mod\ q=x
a m o d q = x ,p、q互质,则
a
m
o
d
(
p
∗
q
)
=
x
a\ mod\ (p*q)=x
a m o d ( p ∗ q ) = x 。
但是,同余不满足同除性,即不满足
a
d
i
v
n
≡
b
d
i
v
n
(
m
o
d
m
)
a\ div\ n\ \equiv\ b\ div\ n(mod\ m)
a d i v n ≡ b d i v n ( m o d m )
由此我们可以有指数取余模板,这里我们直接引用快速幂模板题。
输入整数
m
,
n
,
k
m,n,k
m , n , k ,求
m
n
m
o
d
k
m^n\ mod\ k
m n m o d k 的值。
m
,
n
,
k
∗
k
m, n, k * k
m , n , k ∗ k 为长整型范围内的自然数。
快速幂的原理是,首先将
n
n
n 分解成2的幂次方,例如
3
89
3^{89}
3 8 9 ,可以拆分成
3
64
∗
3
16
∗
3
8
∗
3
1
3^{64}*3^{16}*3^{8}*3^1
3 6 4 ∗ 3 1 6 ∗ 3 8 ∗ 3 1 ,然后循环每次将tmp*=2,判断该位是否存在,累乘即可。这个过程结合代码更易懂,下面直接奉上模板:
#include <iostream>
using namespace std;
typedef long long ll;
int main ( ) {
ll n, m, k;
ll ans = 1 ;
cin >> n >> m >> k;
while ( n) {
if ( n & 1 ) {
ans * = ans * m % k;
}
n >>= 1 ;
m = m * m % k;
}
cout << ans;
return 0 ;
}
快速幂的时间复杂度为
O
(
l
o
g
n
)
O(logn)
O ( l o g n ) ,只要n在long long类型范围内(一般考虑为1e18),都是可行的。