辗转相除法-最大公约数
辗转相除法是求最大公约数的一种方法。它的具体做法是:用较小数除较大数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。这个和更相减损术有着异曲同工之处。
首先介绍下更相减损术的原理,假设有两个数161和63,我们要求这两个数的最大公因数,不妨假定这个最大公因数为m,我们可以将较大的数161看成63+98,63与98的和161可以被m整除,其中63也可以被m整除,自然98可以被m整除;
所以这个问题就转换为求98和63的最大公因数m(和上面m相等)
将98看成63+35,其中63可以被m整除,和98也能被m整除,故35也可以被m整除;
所以问题进一步转换为求35和63的最大公因数m(和上面m相等)
同理转换为求 (63-35)=>28和35 的最大公因数
然后转换为求28和7的最大公因数
…(一直减呀减)
后来转换为求7和7的最大公因数
最后转换为求7和0的最大公因数
输出第一个数字即可;这就是相减损术的原理
我们发现求28和7的最大公约数,一直减7,一直减7…减到不能减为止。这个不断减7的过程就是除7求余数(即%7)
这样我们可以将相减损术优化成辗转相除法,上面给出了思考过程,有兴趣可以百度严谨的证明过程。
int gcb(ll a, ll b) {
if (b == 0)return a;
return gcb(b, a%b);
}
枚举n以内的素数-埃及筛法
更强的解法,将所有偶数过滤掉,可以直接从三开始并且每次乘3,这样
l
o
g
3
(
n
)
log_3(n)
log3(n)
注意事项:
- 数组尽量使用bool型,既节省空间,而且还快(我也不知道为啥快
- 0,1这两个位置一定要初始化为0,不初始化有时会发生不可名状的错误
快速幂运算
与1相与个位为1,简单的移位肯定就把个位的1忽略了,因此要在结果中加上这一项。注意不是else,底下是每一次都要执行的。而加上的这一项与当前的基数是相关的。以
2
15
,
(
n
=
15
)
2^{15},(n=15)
215,(n=15)次方为例
answer | 1 1 1 | 1 ∗ 2 1*2 1∗2 | 1 ∗ 2 ∗ 2 2 1 * 2 * 2^2 1∗2∗22 | 1 ∗ 2 3 ∗ 2 4 1*2^3*2^4 1∗23∗24 | 1 ∗ 2 7 ∗ 2 8 = 2 15 1*2^7*2^8=2^{15} 1∗27∗28=215 |
---|---|---|---|---|---|
base | 2 2 2 | 2 2 2^2 22 | 2 4 2^4 24 | 2 8 2^8 28 | 2 16 2^{16} 216 |
n | 15 | 7 | 3 | 1 | 0 |
每次 n n n是奇数的时候,answer就会乘以当前的base,而base会平方