欧几里得算法
欧几里得算法又称辗转相除法。
功能
首先说一下这个算法是用来干啥的。
欧几里得算法的作用是求两个数
a
a
a和
b
b
b的最大公约数,即
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b).
算法过程
这里再说一下怎么用这个算法求两个数
a
a
a和
b
b
b的最大公约数。
我们不妨设
a
>
b
a>b
a>b。
我们发现如果
b
b
b是
a
a
a的约数,那么
b
b
b就是二者的最大公约数。我们讨论不能整除的情况,即
a
=
b
∗
q
1
+
r
1
a = b * q_1 + r_1
a=b∗q1+r1,其中
a
,
b
,
q
1
,
r
1
a,b,q_1,r_1
a,b,q1,r1都是整数、
r
1
=
a
%
b
r_1=a\%b
r1=a%b,我们通过证明可以得到
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
gcd(a,b)=gcd(b,a \% b)
gcd(a,b)=gcd(b,a%b).
证明
我们只需要证明
a
a
a和
b
b
b 与
b
b
b和
a
%
b
a\%b
a%b 有相同的公因子。
我们设
d
d
d是
a
a
a和
b
b
b 的最大公因子,即
d
∣
a
d|a
d∣a(表示d是a的因子)且
d
∣
b
d|b
d∣b.注意到
r
=
a
−
b
∗
q
r=a-b*q
r=a−b∗q,所以
d
∣
r
d|r
d∣r。又因为
d
∣
b
d|b
d∣b,所以
d
d
d是
b
b
b和
r
r
r的公因子。
反之,如果设
d
∣
b
d|b
d∣b、
d
∣
(
a
%
b
)
d|(a\%b)
d∣(a%b),我们知道
a
=
b
∗
q
+
r
a=b*q+r
a=b∗q+r,所以
d
∣
a
d|a
d∣a,又因为
d
∣
b
d|b
d∣b,所以
d
d
d是
a
a
a和
b
b
b的公因子。
既然两式的公因子相同,那么两式的最大公因子也相同。即
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
gcd(a,b)=gcd(b,a \% b)
gcd(a,b)=gcd(b,a%b).
由此,我们可以持续递归操作,等到
b
=
=
0
b==0
b==0,即上一步
a
%
b
=
=
0
a\%b==0
a%b==0的情况下,求得
a
a
a和
b
b
b的最大公约数。
代码:
int gcd(int a, int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
扩展欧几里得算法
扩展欧几里得算法又称裴蜀定理或贝祖定理,可以用来求一元线性同余方程的解,也即是求一元二次方程的解。
内容
定理:设
a
a
a,
b
b
b是不全为零的整数,则存在整数
x
x
x,
y
y
y,使得
a
∗
x
+
b
∗
y
=
g
c
d
(
a
,
b
)
a*x+b*y=gcd(a,b)
a∗x+b∗y=gcd(a,b).
这个算法是用来判断一元二次方程
a
x
+
b
y
=
c
ax+by=c
ax+by=c是否存在整数解,如果存在求出其的通解。
求解过程
这里给出结论,不做证明,当
g
c
d
(
a
,
b
)
∣
c
gcd(a,b)|c
gcd(a,b)∣c时,一元二次方程有整数解,否则,无整数解。
求解过程:我们假设
a
≥
b
a\ge b
a≥b可知
a
=
b
∗
q
+
r
a=b*q+r
a=b∗q+r,
r
=
a
−
b
∗
q
r=a-b*q
r=a−b∗q,由
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
gcd(a,b)=gcd(b,a \% b)
gcd(a,b)=gcd(b,a%b)知,
a
x
1
+
b
y
1
=
c
ax_1+by_1=c
ax1+by1=c与
b
x
2
+
r
y
2
=
c
bx_2+ry_2=c
bx2+ry2=c有相同的解。即
a
x
1
+
b
y
1
=
b
x
2
+
r
y
2
ax_1+by_1=bx_2+ry_2
ax1+by1=bx2+ry2,如果我们知道
x
2
x_2
x2与
y
2
y_2
y2,我们就可以求
x
1
x_1
x1与
y
1
y_1
y1。
a
x
1
+
b
y
1
=
b
x
2
+
r
y
2
ax_1+by_1=bx_2+ry_2
ax1+by1=bx2+ry2
∵
r
=
a
−
b
∗
q
\because r=a-b*q
∵r=a−b∗q
∵
q
=
⌊
a
b
⌋
\because q=\left\lfloor\dfrac{a}{b}\right\rfloor
∵q=⌊ba⌋
∴
a
x
1
+
b
y
1
=
b
x
2
+
(
a
−
⌊
a
b
⌋
∗
b
)
y
2
\therefore ax_1+by_1=bx_2+(a-\left\lfloor\dfrac{a}{b}\right\rfloor *b)y_2
∴ax1+by1=bx2+(a−⌊ba⌋∗b)y2
∴
a
x
1
+
b
y
1
=
b
x
2
+
a
y
2
−
⌊
a
b
⌋
∗
b
y
2
\therefore ax_1+by_1=bx_2+ay_2-\left\lfloor\dfrac{a}{b}\right\rfloor *by_2
∴ax1+by1=bx2+ay2−⌊ba⌋∗by2
∴
a
x
1
+
b
y
1
=
a
y
2
+
b
(
x
2
−
⌊
a
b
⌋
y
2
)
\therefore ax_1+by_1=ay_2+b(x_2-\left\lfloor\dfrac{a}{b}\right\rfloor y_2)
∴ax1+by1=ay2+b(x2−⌊ba⌋y2)
∴
x
1
=
y
2
\therefore x_1=y_2
∴x1=y2
∴
y
1
=
x
2
−
⌊
a
b
⌋
y
2
\therefore y_1=x_2-\left\lfloor\dfrac{a}{b}\right\rfloor y_2
∴y1=x2−⌊ba⌋y2
我们知道一直递归当
b
=
=
0
b==0
b==0时开始返回,那么当
b
=
=
0
b==0
b==0时,
x
n
x_n
xn和
y
n
y_n
yn应该是多少呢?首先我们来看一下当
b
=
=
0
b==0
b==0时的一元二次方程是什么?答案是:
a
x
n
=
c
ax_n=c
axn=c,对于这个结果我们分开讨论。
当
g
c
d
(
a
,
b
)
=
=
c
gcd(a,b)==c
gcd(a,b)==c,所以
x
n
=
1
x_n=1
xn=1,为了方便计算,我们令
y
n
=
0
y_n=0
yn=0,到此我们求出
x
n
x_n
xn和
y
n
y_n
yn,当我们求出递归本层的
x
n
x_n
xn和
y
n
y_n
yn,我们就可以计算出上一层的
x
n
−
1
x_{n-1}
xn−1和
y
n
−
1
y_{n-1}
yn−1,依次最终可以求出
x
1
x_1
x1和
y
1
y_1
y1,这既是一元二次方程的整数解。
当
g
c
d
(
a
,
b
)
∣
c
gcd(a,b)|c
gcd(a,b)∣c,所以
x
n
=
c
g
c
d
(
a
,
b
)
x_n=\dfrac{c}{gcd(a,b)}
xn=gcd(a,b)c,
x
n
x_n
xn是一个整数,相当于对最终的解扩大了
c
g
c
d
(
a
,
b
)
\dfrac{c}{gcd(a,b)}
gcd(a,b)c,所以我们可以先求出当
g
c
d
(
a
,
b
)
=
=
c
gcd(a,b)==c
gcd(a,b)==c的解,在此基础上扩大
c
g
c
d
(
a
,
b
)
\dfrac{c}{gcd(a,b)}
gcd(a,b)c倍。
当
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)不是
c
c
c的一个因子,那么
x
n
=
c
g
c
d
(
a
,
b
)
x_n=\dfrac{c}{gcd(a,b)}
xn=gcd(a,b)c,
x
n
x_n
xn不是一个整数,那么最终解非整数,即一元二次方程无整数解。
到此我们给出了一元二次方程解的所有情况,我们知道当存在整数解时,求得的一元二次方程的解不止一个。我们可以求出其通解为
x
=
x
+
b
/
d
∗
k
x=x+b/d*k
x=x+b/d∗k,
y
=
y
−
a
/
d
∗
k
y=y-a/d*k
y=y−a/d∗k.
下面给出代码:
int exgcd(int a,int b, int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int d = exgcd(b,a%b,x,y);
int x1 = x;
x = y;
y = x1-a/b*y;
return d;
}
int main()
{
int a,b,c,x,y;
scanf("%d%d%d",&a,&b,&c);
int d = exgcd(a,b,x,y);
if((a==0&&b==0)||c%d!=0)
{
printf("无整数解");
}
else
{
int n = c/d;
x *= n;
y *= n;
printf("一个整数解为x=%d y=%d\n",x,y);
printf("通解为x=x+b/d*k,y=y-a/d*k\n");
}
return 0;
}
唯一分解定理
定理
每个大于1的正整数n都可以被唯一地写成素数的乘积,在乘积中的素因子按照非降序排列。正整数n的分解式 n = p 1 e 1 ∗ p 2 e 2 ∗ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ∗ p k e k n=p_1^{e_1}*p_2^{e_2}*······*p_k^{e_k} n=p1e1∗p2e2∗⋅⋅⋅⋅⋅⋅∗pkek,称为n的标准分解式,其中 p 1 p_1 p1, p 2 p_2 p2, ⋅ ⋅ ⋅ ··· ⋅⋅⋅, p k p_k pk是素数, p 1 ≤ p 2 ≤ ⋅ ⋅ ⋅ ≤ p k p_1 \le p_2 \le ···\le p_k p1≤p2≤⋅⋅⋅≤pk,且 e 1 e_1 e1, e 2 e_2 e2, ⋅ ⋅ ⋅ ··· ⋅⋅⋅, e k e_k ek是正整数。
性质
- 若n的标准素因子分解表达式为
n
=
p
1
e
1
∗
p
2
e
2
∗
⋅
⋅
⋅
⋅
⋅
⋅
∗
p
k
e
k
n=p_1^{e_1}*p_2^{e_2}*······*p_k^{e_k}
n=p1e1∗p2e2∗⋅⋅⋅⋅⋅⋅∗pkek,设d(n)为n的正因子的个数。s(n)为n的所有因子之和,则有
d
(
n
)
=
(
e
1
+
1
)
∗
(
e
2
+
1
)
∗
⋅
⋅
⋅
∗
(
e
k
+
1
)
d(n)=(e_1+1)*(e_2+1)*···*(e_k+1)
d(n)=(e1+1)∗(e2+1)∗⋅⋅⋅∗(ek+1)
s
(
n
)
=
p
1
e
1
+
1
−
1
p
1
−
1
∗
p
2
e
2
+
1
−
1
p
2
−
1
∗
⋅
⋅
⋅
∗
p
k
e
k
+
1
−
1
p
k
−
1
s(n)= \dfrac{p_1^{e_1+1}-1}{p_1-1}* \dfrac{p_2^{e_2+1}-1}{p_2-1}*···* \dfrac{p_k^{e_k+1}-1}{p_k-1}
s(n)=p1−1p1e1+1−1∗p2−1p2e2+1−1∗⋅⋅⋅∗pk−1pkek+1−1
上边公式不做证明,给出解释。例如 n = 12 n=12 n=12, n n n的因子有 1 , 2 , 3 , 4 , 6 , 12 1,2,3,4,6,12 1,2,3,4,6,12,通过暴力计算,因子个数 d 1 ( 12 ) = 6 d_1(12)=6 d1(12)=6,因子和 s 1 ( 12 ) = 28 s_1(12)=28 s1(12)=28,唯一分解式 12 = 2 2 ∗ 3 1 12=2^2*3^1 12=22∗31,通过公式计算,因子个数 d ( 12 ) = ( 2 + 1 ) ∗ ( 1 + 1 ) = 6 d(12)=(2+1)*(1+1)=6 d(12)=(2+1)∗(1+1)=6,因子和 s ( 12 ) = 2 2 + 1 − 1 2 − 1 ∗ 3 1 + 1 − 1 3 − 1 = 7 ∗ 4 = 28 s(12)= \dfrac{2^{2+1}-1}{2-1}* \dfrac{3^{1+1}-1}{3-1}=7*4=28 s(12)=2−122+1−1∗3−131+1−1=7∗4=28 - 设 a = p 1 α 1 ∗ p 2 α 2 ∗ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ∗ p k α k a=p_1^{α_1}*p_2^{α_2}*······*p_k^{α_k} a=p1α1∗p2α2∗⋅⋅⋅⋅⋅⋅∗pkαk, b = p 1 β 1 ∗ p 2 β 2 ∗ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ∗ p k β k b=p_1^{β_1}*p_2^{β_2}*······*p_k^{β_k} b=p1β1∗p2β2∗⋅⋅⋅⋅⋅⋅∗pkβk,则有: g c d ( a , b ) = p 1 m i n ( α 1 , β 1 ) ∗ p 2 m i n ( α 2 , β 2 ) ∗ ⋅ ⋅ ⋅ ∗ p k m i n ( α k , β k ) gcd(a,b)=p_1^{min(α_1,β_1)}*p_2^{min(α_2,β_2)}*···*p_k^{min(α_k,β_k)} gcd(a,b)=p1min(α1,β1)∗p2min(α2,β2)∗⋅⋅⋅∗pkmin(αk,βk) l c m ( a , b ) = p 1 m a x ( α 1 , β 1 ) ∗ p 2 m a x ( α 2 , β 2 ) ∗ ⋅ ⋅ ⋅ ∗ p k m a x ( α k , β k ) lcm(a,b)=p_1^{max(α_1,β_1)}*p_2^{max(α_2,β_2)}*···*p_k^{max(α_k,β_k)} lcm(a,b)=p1max(α1,β1)∗p2max(α2,β2)∗⋅⋅⋅∗pkmax(αk,βk)
- 如果 a a a和 b b b是正整数,则: l c m ( a , b ) = a ∗ b / g c d ( a , b ) lcm(a,b)=a*b/gcd(a,b) lcm(a,b)=a∗b/gcd(a,b)
- n ! n! n!的素因子分解中的素数p的幂为: ⌊ n p ⌋ + ⌊ n p 2 ⌋ + ⌊ n p 3 ⌋ + ⋅ ⋅ ⋅ \left\lfloor\dfrac{n}{p}\right\rfloor+\left\lfloor\dfrac{n}{p^2}\right\rfloor+\left\lfloor\dfrac{n}{p^3}\right\rfloor+··· ⌊pn⌋+⌊p2n⌋+⌊p3n⌋+⋅⋅⋅