算法手册:Clegg L E, Mac Gabhann F. Molecular mechanism matters: Benefits of mechanistic computational models for drug development[J]. Pharmacological Research, 2015, 99: 149-154.
扩展欧几里得算法
给定 a , b a,b a,b,计算 ( x , y , d ) (x,y,d) (x,y,d),使满足: a x + b y = d , d = g c d ( a , b ) ax+by=d,\, d=gcd(a,b) ax+by=d,d=gcd(a,b)
易知:
a
⋅
1
+
b
⋅
0
=
a
a
⋅
0
+
b
⋅
1
=
b
\begin{aligned} a \cdot 1 + b \cdot 0 = a\\ a \cdot 0 + b \cdot 1 = b\\ \end{aligned}
a⋅1+b⋅0=aa⋅0+b⋅1=b
以它为初值,令:
a
⋅
x
1
+
b
⋅
y
1
=
u
⋯
⋯
(
∗
)
a
⋅
x
2
+
b
⋅
y
2
=
v
⋯
⋯
(
∗
∗
)
\begin{aligned} a \cdot x_1 + b \cdot y_1 =& u \,\,\cdots \cdots (*)\\ a \cdot x_2 + b \cdot y_2 =& v \,\,\cdots \cdots (**)\\ \end{aligned}
a⋅x1+b⋅y1=a⋅x2+b⋅y2=u⋯⋯(∗)v⋯⋯(∗∗)
如果
u
≠
0
u \not = 0
u=0,那么执行欧几里得算法:
- 计算
q = ⌊ v u ⌋ q = \lfloor \frac{v}{u} \rfloor q=⌊uv⌋
- 令
( ∗ ) → ( ∗ ∗ ) ( ∗ ∗ ) − q ( ∗ ) → ( ∗ ) \begin{aligned} (*) \rightarrow& (**)\\ (**) - q (*) \rightarrow& (*)\\ \end{aligned} (∗)→(∗∗)−q(∗)→(∗∗)(∗)
- 即
( x 2 , y 2 , v ) ← ( x 1 , y 1 , u ) ( x 1 , y 1 , u ) ← ( x 2 − q x 1 , y 2 − q y 1 , v − q u ) \begin{aligned} (x_2,y_2,v) \leftarrow& (x_1,y_1,u)\\ (x_1,y_1,u) \leftarrow& (x_2-qx_1,y_2-qy_1,v-qu)\\ \end{aligned} (x2,y2,v)←(x1,y1,u)←(x1,y1,u)(x2−qx1,y2−qy1,v−qu)
注意数据依赖,实例化时要使用临时变量暂存。
直到 u = 0 u=0 u=0结束,有 a x 2 + b y 2 = v ax_2+by_2=v ax2+by2=v,得出结果 ( x = x 2 , y = y 2 , d = v ) (x=x_2,y=y_2,d=v) (x=x2,y=y2,d=v)
def exgcd(a,b):
'xa + yb = d, (x,y,d)'
if a>b:
x1,y1,d1 = 1,0,a
x2,y2,d2 = 0,1,b
else:
x1,y1,d1 = 0,1,b
x2,y2,d2 = 1,0,a
while d2 != 0:
t = d1//d2
x1,y1,d1 = x1-t*x2, y1-t*y2, d1-t*d2
x1,y1,d1,x2,y2,d2 = x2,y2,d2,x1,y1,d1
return x1,y1,d1
二进制欧几里得算法
给定 a , b a,b a,b,计算 d d d,使满足: d = g c d ( a , b ) d=gcd(a,b) d=gcd(a,b)
假设
a
,
b
a,b
a,b都是偶数,那么
gcd
(
a
,
b
)
=
2
gcd
(
a
2
,
b
2
)
\gcd(a,b) = 2\gcd(\dfrac{a}{2},\dfrac{b}{2})
gcd(a,b)=2gcd(2a,2b)
因此,计算
e
=
2
k
e=2^k
e=2k,使得
a
′
=
a
e
,
b
′
=
b
e
a'=\dfrac{a}{e},b'=\dfrac{b}{e}
a′=ea,b′=eb不全为偶数
那么
gcd
(
a
,
b
)
=
e
⋅
gcd
(
a
′
,
b
′
)
2
∤
g
c
d
(
a
′
,
b
′
)
\begin{aligned} \gcd(a,b) =& e \cdot \gcd(a',b')\\ 2 \nmid& gcd(a',b') \end{aligned}
gcd(a,b)=2∤e⋅gcd(a′,b′)gcd(a′,b′)
我们只需计算
gcd
(
a
′
,
b
′
)
\gcd(a',b')
gcd(a′,b′)。令
u
=
a
′
,
v
=
b
′
u=a',v=b'
u=a′,v=b′
若
u
u
u是偶数且
v
v
v是奇数,那么
g
c
d
(
u
,
v
)
=
g
c
d
(
u
2
,
v
)
gcd(u,v) = gcd(\frac{u}{2},v)
gcd(u,v)=gcd(2u,v)
当
u
≠
0
u \not = 0
u=0,执行欧几里得算法:
- 若 u u u是偶数,那么反复执行 u ← u / 2 u \leftarrow u/2 u←u/2
- 若 v v v是偶数,那么反复执行 v ← v / 2 v \leftarrow v/2 v←v/2
- 当 u ≥ v u \ge v u≥v,令 u ← u − v u \leftarrow u-v u←u−v;否则 v ← v − u v \leftarrow v-u v←v−u
当 u = 0 u=0 u=0时结束,此时 v = g c d ( a ′ , b ′ ) v=gcd(a',b') v=gcd(a′,b′),得出结果 d = e ⋅ v d = e \cdot v d=e⋅v
注意,反复执行除二操作,可以用一次右移代替。
二进制求逆算法
对于奇素数 p p p,给定 a ∈ Z p ∗ a \in Z_p^* a∈Zp∗,计算 x = a − 1 m o d p x = a^{-1}\mod p x=a−1modp
易知:
a
⋅
1
+
p
⋅
0
=
a
a
⋅
0
+
p
⋅
1
=
p
\begin{aligned} a \cdot 1 + p \cdot 0 = a\\ a \cdot 0 + p \cdot 1 = p\\ \end{aligned}
a⋅1+p⋅0=aa⋅0+p⋅1=p
以它为初值,令:
a
⋅
x
1
+
p
⋅
y
1
=
u
⋯
⋯
(
∗
)
a
⋅
x
2
+
p
⋅
y
2
=
v
⋯
⋯
(
∗
∗
)
\begin{aligned} a \cdot x_1 + p \cdot y_1 =& u \,\,\cdots \cdots (*)\\ a \cdot x_2 + p \cdot y_2 =& v \,\,\cdots \cdots (**)\\ \end{aligned}
a⋅x1+p⋅y1=a⋅x2+p⋅y2=u⋯⋯(∗)v⋯⋯(∗∗)
我们只计算
x
1
,
x
2
x_1,x_2
x1,x2,不计算
y
1
,
y
2
y_1,y_2
y1,y2 (也不容易计算)
易知, x ∈ Z p ∗ x \in Z_p^* x∈Zp∗
如果 u ≠ 1 ∧ v ≠ 1 u \not = 1 \wedge v \not = 1 u=1∧v=1,那么执行欧几里得算法:
- 若
u
u
u是偶数,那么反复执行
- u ← u / 2 u \leftarrow u/2 u←u/2
- 若 x 1 x_1 x1是偶数,令 x 1 ← x 1 / 2 x_1 \leftarrow x_1/2 x1←x1/2;否则 x 1 ← ( x 1 + p ) / 2 x_1 \leftarrow (x_1 + p)/2 x1←(x1+p)/2
- 若
v
v
v是偶数,那么反复执行
- v ← v / 2 v \leftarrow v/2 v←v/2
- 若 x 2 x_2 x2是偶数,令 x 2 ← x 2 / 2 x_2 \leftarrow x_2/2 x2←x2/2;否则 x 2 ← ( x 2 + p ) / 2 x_2 \leftarrow (x_2 + p)/2 x2←(x2+p)/2
- 当 u ≥ v u \ge v u≥v,令 u ← u − v , x 1 = x 1 − x 2 u \leftarrow u-v,\, x_1 = x_1-x_2 u←u−v,x1=x1−x2;否则 v ← v − u , x 2 = x 2 − x 1 v \leftarrow v-u,\, x_2 = x_2-x_1 v←v−u,x2=x2−x1
当 u = 1 u=1 u=1时, a ⋅ x 1 ≡ u m o d p a\cdot x_1 \equiv u \mod p a⋅x1≡umodp,得出结果 x = x 1 x=x_1 x=x1
当 v = 1 v=1 v=1时, a ⋅ x 2 ≡ v m o d p a\cdot x_2 \equiv v \mod p a⋅x2≡vmodp,得出结果 x = x 2 x=x_2 x=x2
如果初值设为 x 1 = b ∈ Z p x_1=b \in Z_p x1=b∈Zp而非 x 1 = 1 x_1=1 x1=1,那么上述算法的结果为 b a − 1 m o d p ba^{-1} \mod p ba−1modp,即:计算除法不再需要额外的乘法!