ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

算法题解----分解质因数 + 筛质数的三种算法

2021-08-21 01:02:31  阅读:193  来源: 互联网

标签:埃氏 int 题解 质数 算法 primes 质因数


第一部分 : 分解质因数

任何一个大于 1 的正整数都可以写成这样的形式:

  

其中 Pi 是 一个质数

那么我们可以用怎么样的算法去得到 这个正整数的 质因数以及其 指数呢?

我们可以用 试除法这个方法:
① 找到N的一个 质约数 然后让N一只除这个质约数,直到 N % Pi != 0 

② 记录我们除这个质约数除了多少次 那么次数就是这个质约数的指数

这里还有几点要注意:

我们循环控制变量i 是这样循环的 for( i = 2 ; i <= n/i ; i++)

这样就可以找到N的绝大部分质因数 不过有可能我们会漏掉一个质因数

比如说当N很大的时候 他可能有一个质因数是大于 sqrt(N) 的

所以我们最后要进行一个判断 if( N>1 ) 那么最后N就是原来N的最后一个最大的质因数 而且这个质因数的指数一定是1

 

话不多说,上代码~

 

 

int cnt,primes[N];                            //存储质因数
int s[N];                                     //存储指数    

void divide(int n)
{
    for(int i = 2 ; i <= n / i ; i ++)
    {
         if(n % i == 0)
         {   
               primes[cnt++] = i;
               while(n%i)
             {
                 s[cnt]++;
                 n /= i;
             }
    }
    
      if(n>1)
     {
         primes[cnt] = n;
         s[cnt] = 1; 
     }
}    

 

 

 

 第二部分:筛质数

学过编程的同学一定都写过筛质数的程序吧

很经典的一道题 : 筛取1000以内的质数

里面有一种比较好的算法:

 

bool is_prime(int n)
{
    for(int i=2 ; i<=n/i;i++)
    {
          if(n % i ==0)
          {
                return false;
           } 
    }
    return true;
}    

 

这就是试除法筛素数的算法,那么为什么我们要设置 i <= n/i 而不是 i <= n-1 呢 ?

因为我们这个算法是用来判断这个数是不是素数,如果这个数是合数那个它一定可以写成 a * b 且 a !=1 b != 1的形式 这是完全对称的,所以只用判断i到 sqrt(n)就可以了 。这个算法的时间复杂度为O(n logn)

那么对于筛素数我们有没有更高效的算法呢?

这里我就介绍两种筛素数的算法: 埃氏筛和线性筛

首先介绍埃氏筛

 

我们还要用一个st数组来存储每个数的状态,如果这个数被筛掉了就把这个st设置为true

话不多说 上代码

int cnt,primes[N];
bool st[N];
void get_primes(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i])                    //如果i是质数
        {
             primes[cnt++] = i;
             for(int j = i ; j <=n ;j+=i) st[j]=true;   //筛去i的倍数
         }
    }  

}

 

埃氏筛的算法时间复杂度为O(n loglogn) 是十分接近O(n)的时间复杂度的, 也是算法竞赛常用的筛质数的算法

为什么埃氏筛的时间复杂度不是O(n)的呢?

因为 如果用埃氏筛的算法 一个数可能要被筛掉很多次 。

我再来介绍一个更好的算法去筛质数:线性筛,从名字来看就知道线性筛的时间复杂度是O(n)的,那么线性筛是如何筛掉合数的呢?

其实线性筛的本质也是筛掉质数的倍数,不过它中间的过程和埃氏筛有点不同

埃氏筛是只要是质数是当前合数的质因子就筛

而线性筛思路是这样的,如果质因数是当前数的最小质因子,那么这个质因数也一定是这个质因数乘以当前数的最小质因子,那么就可以筛掉

避免了一个数被重复筛去的情况,好,那么代码是如何写的呢?

void get_primes(int n)
{
     for(int i=2 ;i<=n;i++)
     {
         if(!st[i]) primes[cnt++] = i;
         for(int j = 0; primes[j] <= n/i;j++)
         {
               st[primes[j] * i] = true;
               if(i % primes[j] == 0) break;
          }     
     }    
}

 

标签:埃氏,int,题解,质数,算法,primes,质因数
来源: https://www.cnblogs.com/apakchan/p/15168661.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有