算法--数论

这里写目录标题

  • 质数(素数)
    • 定义
    • 判断是否为质数
      • 暴力写法,试除法
        • 基本思想
        • 具体写法
      • 优化
        • 基本思想(时间复杂度根号n)
        • 具体写法
    • 分解质因数
      • 分析题意
      • 暴力写法
        • 基本思想
        • 具体代码
      • 优化
        • 基本思想(时间复杂度小于等于根号n)
        • 具体代码
    • 筛质数(区别于判断质数,这个是筛选出来并保存,质数的数目较多)
      • 基本思想
      • 具体代码
      • 优化(埃氏算法)
        • 基本思想(时间复杂度约为n)
        • 具体代码
      • 优化2(线性筛法)
        • 基本思想
        • 具体代码
  • 一级目录
    • 二级目录
    • 二级目录
    • 二级目录
  • 一级目录
    • 二级目录
    • 二级目录
    • 二级目录
  • 一级目录
    • 二级目录
    • 二级目录
    • 二级目录

质数(素数)

定义

算法--数论_第1张图片

判断是否为质数

暴力写法,试除法

基本思想

从定义出发,判断是否为质数
1、小于2的数,统一返回false
2、遍历 i 从2到小于n(即除去1和n)
判断是否有n % i == 0 的,表示这中间有i可以整除,如果有,返回false

最后返回true

具体写法

算法--数论_第2张图片

优化

基本思想(时间复杂度根号n)

算法--数论_第3张图片
利用质数的性质,当d能被n整除时,n/d 也能被n整除,
所以,只需要判断从2到根号n有无能让d整除的数即可

具体写法

算法--数论_第4张图片
这里的 i 就是上面的d,循环 i 判断是否有数能让n整除,也就是上面的判断d是否能让n整除

分解质因数

分析题意

算法--数论_第5张图片
质因子分解,就是输出几组质数并输出他们对应的数量,他们乘积等于输入的数

暴力写法

基本思想

直接循环所有从2到等于n的数,如果能找到一个被n整除的 i ,那么 i 一定是一个质数,这里与上面判断质数的代码要区分开,
上面写到:
for循环里,if(n % i == 0) return false
因为上面是判断n是否为质数,跟 i 没有关系
而本题的重点不在n,而是他的因子 i,所以这里当可以整除时, i 一定是一个质数,这句话就不会与上面矛盾了

具体代码

算法--数论_第6张图片
纠正:int x 改为 int n
循环i从2到小于等于n,其中如果找到了一个i能被n整除,那么这个i一定是质数,他就是我们要找的质因子之一(具体原因见上方“基本思想”),之后循环计算 i 的次数即可
循环计算质数次数时:
首先定义一个计数器s=0;
之后,while循环,条件是n 还可以整除 i
条件成立,就更新n 为 n/i,(因为题设是多个质因子的乘积,所以要进行下一步判断的话,要先将已经判断出来的 i 除去)
之后计数器++
输出质子以及出现的次数

优化

基本思想(时间复杂度小于等于根号n)

算法--数论_第7张图片
利用性质:n中最多只包含一个大于根号n的质因子
证明:如果有两个大于跟好n的质因子,那么这两个相乘,一定大于n,不成立,所以该性质成立,我们可以利用这个性质进行优化

具体代码

算法--数论_第8张图片

将for循环的 i ,从2开始循环到 小于等于n/i
然后,其他的不变,在for循环结束之后,如果n>1(因为n在上面的过程中,不断的被除开,不断的变小,被除开的原因见上面“未优化时具体代码的解释”),那么这个n就是那个大于根号n的质因子,他的个数永远为1,因为只存在一个大于根号n的质因子

tip:puts(“”);可以输出一行回车
同时puts(“字符串”);可以输出字符串

筛质数(区别于判断质数,这个是筛选出来并保存,质数的数目较多)

基本思想

算法--数论_第9张图片
从2开始,删除后面2的倍数、删除3的倍数、4、5…
最后留下的都是质数,
因为假设p被留下了,那么就是前面2到p-1都没能把p删掉,也就是前面的倍数都没有p,所以p也就没有除去1和本身以外的因子,所以p一定是质数

具体代码

算法--数论_第10张图片
纠正:17行 primes【】= i
prime数组用来存放质数
cnt用来移动prime数组里的坐标,同时也在计数
st数组用来记录某个数是否被删掉了

首先从2到小于等于n遍历 i
之后 直接判断是否st[i]为假,如果是,那么放入prime数组中,并且cnt++
if之后,使用for循环对倍数进行删除:
初始化 j 为 i+i ; j <=n ; j += i
st[j]=true
初始化为 i 的2倍,之后递增条件是在 j 的基础上依次加 i,这样就可以找到 i 的所有倍数

优化(埃氏算法)

基本思想(时间复杂度约为n)

算法--数论_第11张图片
我们的目的是删掉合数,
任何一个合数都会被筛掉,因为质数的倍数包括所有的合数,任何一个合数都有一个质因子
所以我们只需要删除出来前面质数的倍数即可

具体代码

算法--数论_第12张图片
纠正:17行 primes【】= i
将for循环放入if里面即可

优化2(线性筛法)

基本思想

算法--数论_第13张图片
埃氏筛法:
我们的目的是删掉合数,
任何一个合数都会被筛掉,因为质数的倍数包括所有的合数,任何一个合数都有一个质因子
所以我们只需要删除出来前面质数的倍数即可

线性筛法的思路仍然是删掉质数的倍数 , 但是这种算法是根据每个最小质因子的倍数去筛,效率更高

具体代码

算法--数论_第14张图片
仍然是for循环 i 从2到小于等于 n
之后if不变
改变一下第二个for循环 :
j初始化为0 ;之后primes[j]<= n/i ;j++
然后标记st[primes[ j ] * i ]=true; (删除每个最小质因子的倍数)
之后加一个if (i % primes[ j ] == 0) break; (这一步可以保证primes[ j ]是 i 的最小质因子)

注意点:关于筛质数的三个算法中,只有该算法的第二个for循环不同于其他两个,前两个的第二个for循环都一样,只是位置不同,要特别注意

一级目录

二级目录

二级目录

二级目录

一级目录

二级目录

二级目录

二级目录

一级目录

二级目录

二级目录

二级目录

你可能感兴趣的:(算法)