数论1素数的筛法以及质因数分解

一.素数
定义:若一个正整数无法被除了1和它自身以外的任何自然数整除,那么称这个数为素数,否则为合数。1既不是素数也不是合数。
一般对于一个比较大的数N来说,不超过N的质数大约有N/ln N个素数,可以通过该方法来大致估算时间复杂度

素数的判定:
1.试除法:由于过于简单,便不多做赘述
2.埃氏筛法:方法是对于每个素数n,都筛掉它的倍数,2n,3n…,而我们考虑到对于某些数比如2或者3都能筛掉6,故可以采用一些方法进行优化:
即只需要从n*n开始筛即可
这种方法的时间复杂度是O(nloglogn)
相关的代码模板:

for(int i=2;i<=n;i++)
 {
     if(!st[i])   //st用来标记某个数是否为素数
     {
         for(int j=i;j<=n/i;j++) {  //从x的平方开始筛
             st[i*j]=true;
          
         }
     }
 }

3.线性筛:对于埃氏筛来说它仍然会筛掉一些重复元素比如12会被3和2都筛一次,这是因为12=3 * 4和12=6 * 2,其中12可以表示成两种方法,且每种方法都有一个质因子,那我们是不是可以考虑一种方法,使得所有数都只能有一种表示方法呢,这就是线性筛的思想:对于所有数,用它的最小质因子筛,比如12=2 * 2 * 3,36=2 * 2 * 3 * 3,这样就能保证所有数都只能被筛一次了
这样的时间复杂度刚好是O(n),故这就是线性筛名字的来由
这里先说一下算法流程:
1.对于所有的数,都遍历一遍,如果当前元素是素数,那么就把它加到现有的数组里面去
2.当数遍历到i的时候,对当前数组里的所有素数都筛掉i*primes[j]
3.当primes[j]刚好是i的最小质因子时结束
其中第三点是最重要的,为什么必须得在这个时候结束呢,我们设某个数为某个时刻 i=a * b,其中a为i的最小质因子,假设我们此时没有结束,那么其可能会筛掉某个数c=a * b * d,由于此时d应该大于a,那么c=a * (b * d),即c还会被b *d给重复筛去
这里给出模板

for(int i=2;i<=n;i++)
 {
    if(!st[i]) primes[res++]=i;   //st用来判断某个数是否为素数,primes用来存放已有素数
    for(int j=0;j<=res&&i<=n/primes[j];j++)
    {
        st[i*primes[j]]=true;
        if(i%primes[j]==0) break;
    }
 }

质因数分解:根据算数基本定理,任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作N=p1^c1 * p2^c2 * p3^c3 *… *pn^cn,其中c都是正数且p都是素数,且满足p1<p2<…<pn;
结合素数判定里的试除法和埃氏筛法,我们可以扫描所有2~根号n之间的每个数d,如果d能整除N,则从N中除去d,累计除去d的次数即为该数的指数、
时间复杂度是O(根号N)

for(int i=2;i<=a/i;i++)
       if(a%i==0)
        {    int s=0;
            while(a%i==0)
           {
               a/=i;
               s++;
           }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值