算法学习过程——数论基础

数论基础之——整除

较为基础的内容,两数相除余数为0则为整除

设a , b \in Z,存在 q 使得 b = q * a,则 b 能被 a 整除;记作 a | b

整除性质
  • a | b \Leftrightarrow -a | b \Leftrightarrow a | -b \Leftrightarrow |a| | |b|
  • a | b \wedge b | c \Rightarrow a | c
  • a | b \wedge a | c \Leftrightarrow \forall x, y \in Z, a | (xb + yc)
数论基础之——约数

定义:若 a 能整除 b ,则称 b 是 a 的倍数,a 是 b 的约数。

性质:

  • 设整数 b (b不为0),当 一个数 d 遍历 b 的全部约数时,\frac{b}{d} 也遍历 b 的全体约数
  • 设整数 b > 0,则当 d 遍历 b 的全体正约束的时候,\frac{b}{d} 也遍历 b 的全部正约数

最大公因数和最小公倍数

定义:多个数共有的因数称为公因数,其中最大的为最大公因数。记作(a, b)

          多个数共有的倍数称为公倍数,其中最小的为最小公倍数 。记作[a, b]

          
最大公因数的求法
  • 欧几里得算法

如果我们已知两个数  a 和 b,如何求出二者的最大公约数呢?不妨设 a > b

我们发现如果  b  是  a  的约数,那么  b 就是二者的最大公约数。 下面讨论不能整除的情况,即 a = b * q + r,其中 r < b 

我们可以通过证明得到gcd(a , b) = gcd(b, a mod b)

(注:a | b 表示 b 能整除 a,b mod a = 0。)

既然得到了gcd (a, b) = gcd(b, r),这里两个数的大小是不会增大的,那么我们也就得到了关于两个数的最大公约数的一个递归求法。

// Version 1
int gcd(int a, int b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

// Version 2
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }

递归至 b = 0(即上一步的 a % b == 0)的情况再返回值即可。

根据上述递归求法,我们也可以写出一个迭代求法:

int gcd(int a, int b) {
  while (b != 0) {
    int tmp = a;
    a = b;
    b = tmp % b;
  }
  return a;
}

另外,对于 C++17,我们可以使用 <numeric> 头中的 std::gcd 与 std::lcm 来求最大公约数和最小公倍数。

多个数的最大公因数

那怎么求多个数的最大公约数呢?显然答案一定是每个数的约数,那么也一定是每相邻两个数的约数。我们采用归纳法,可以证明,每次取出两个数求出答案后再放回去,不会对所需要的答案造成影响。

最小公倍数

一组整数的公倍数,是指同时是这组数中每一个数的倍数的数。0 是任意一组整数的公倍数。

一组整数的最小公倍数,是指所有正的公倍数里面,最小的一个数。

两个数 a = p_{1}^{k_{a1}}p_{2}^{k_{a2}}p_{3}^{k_{a3}}...p_{s}^{k_{as}}, b = p_{1}^{k_{b1}}p_{2}^{k_{b2}}p_{3}^{k_{b3}} ...p_{s}^{k_{bs}}

我们发现,对于 a 和 b 的情况,二者的最大公约数等于 p_{1}^{min(k_{a1},k_{b1})}p_{2}^{min(k_{a2},k_{b2})}p_{3}^{min(k_{a3},k_{b3})}...

最小公倍数为p_{1}^{max(k_{a1},k_{b1})}p_{2}^{max(k_{a2},k_{b2})}p_{3}^{max(k_{a3},k_{b3})}...

由于 k_{a} + k_{b} = max(k_{a},k_{b}) + min(k_{a},k_{b})

gcd(a, b) * lcm(a, b) = a * b。要求两个数的最小公公倍数,先求出最大公因数即可。

int lcm(int a,int b)
{
    return (a/gcd(a,b))*b;//防止数据溢出
}

素数与合数

设整数 p \neq 0,1,-1。如果 p 除了平凡约数( 1 和 它本身 为平凡约数)外没有其他约数,那么称 p 为 素数(不可约数)

若整数 a \neq 0,1,-1。且a 不是素数,则称 a 为合数。

简单性质

算数基本引理

设 p 是素数,p|a_{1}a_{2},那么  p|a_{1}  和  p|a_{2}  至少有一个成立。

唯一分解定理

设正整数 a ,那么必有表示:a = p_{1}p_{2}p_{3}...p_{s}

其中p_{j}\left ( 1\leq j\leq s \right )是素数。且在不计次序的意义下,该表示唯一

标准素因数分解式

a = p_{1}^{a_{1}}p_{2}^{a_{2}}p_{3}^{a_{3}}...p_{s}^{a_{s}},p_{1}< p_{2}< p_{3}< ... < p_{s}

称为正整数 a 的标准素因数分解式

C/C++的整数除法和取模运算

在 C/C++ 中,整数除法和取模运算,与数学上习惯的取模和除法不一致。

对于所有标准版本的 C/C++,规定在整数除法中:

  1. 当除数为 0 时,行为未定义;
  2. 否则 (a / b) * b + a % b 的运算结果与 a 相等。

也就是说,取模运算的符号取决于除法如何取整;而除法如何取整,这是实现定义的(由编译器决定)。

从 C99和 C++11标准版本起,规定 商向零取整(舍弃小数部分);取模的符号即与被除数相同。从此以下运算结果保证为真:

  1. 5 % 3 == 2;
  2. 5 % -3 == 2;
  3. -5 % 3 == -2;
  4. -5 % -3 == -2;

总结

初步学习数学和计算机都会学到的基础知识,自用复习以及分享给大家,有任何问题可以留言或私信。

  • 28
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值