数论之素数(质因数分解与筛法)

一、前提
1.素数又称质数,有无限个。除了1和它本身以外不再有其他的除数整除。
2.算术基本定理:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。
例如:6936=( 23 2 3 )( 172 17 2 )*3,1200= ( 24 2 4 )( 52 5 2 )*3 。
二、质因数分解
1.定义:
每个合数都可以写成几个素数相乘的形式,其中每个素数叫做这个合数的素因数
把一个合数用素因数相乘的形式表示出来,叫做质因数分解。
2.分解素因数——短除法
(1)先用一个能整除这个合数的素数(通常从最小的开始)去除。
(2)得出的商如果是合数,再按照上面的方法继续除下去,直到得出的商是素数为止。
(3)然后把各个除数和最后的商按从小到大的顺序写成连乘的形式。

注意:任何一个合数n至多会有一个大于根号n的因子。(若0个,n为a的平方;若1个,n的素因数一个大于a一个小于a)
n=( n n )*( n n )
n的因数除了根号n,其他都是成对存在的,且必定一个大于 n n 一个小于 n n
假设n不是质数,有个因数大于 n n (不是N本身)
则n必定有一个与之对应的小于 n n 的因数
也就是说,如果2到 n n 都没有n的因数,那么对应的 n n 到n-1都没有n的因数,n就是个质数

cnt=0; //素因子个数
for(int i=2;i*i<=n;i++)//这里是i²啊!
{
        if(n%i==0)
        {
            ++cnt;
            p[cnt]=i;//p数组存素因子
            num[cnt]=0;//num数组:每个素因子的指数,此处是初始化为0
            while(n%i==0)
            {
                ++num[cnt];
                n/=i;
            }
        }
}
if(n>1)
{
     ++cnt;
     p[cnt]=n;
     num[cnt]=1;
}

三、判断素数
1.遍历2-n的数

test(int n)
{
   for (int i=2; i<=sqrt(n); i++)//一个数至少有一个比sprt(n)小的质因数。
        if (n % i == 0)
            return false;   // 不是质数
    return true;    // 是质数
}

2.Eratosthenes筛法
算法描述:
(1)列出所有正整数。
(2)从2开始,删掉 2 的倍数。找下一个未被删掉的数字。
(3)找到 3 ,删掉 3 的倍数。找下一个未被删掉的数字
(4)找到 5 ,删掉 5 的倍数。

重复步骤,就能删掉所有合数,找到所有质数。
这里写图片描述

bool prime[20000000];
void eratosthenes()
{
    memset(prime,1,sizeof(prime));//初始化为1,全部是质数
    prime[0] = 0;  prime[1] = 0;  // 0 和 1 不是质数
    for (int i=2; i<20000000; i++)
        if (prime[i]==1) // 删掉质数i的倍数 
           for (int **j=i+i**; j<20000000; j+=i)
                prime[j] = 0;
}

注意:删掉质数 i 的倍数时,早已删掉1 倍~ i-1 倍之间的合数了,所以直接从i倍开始删除。
代码可优化如下:

void eratosthenes()
{
    memset(prime,1,sizeof(prime));
    prime[0] = 0;prime[1] = 0;
    for (int i=2; i<20000000; i++)
        if (prime[i]==1)//删掉i的倍数从i倍开始
   for (int j=i*i; j<20000000; j+=i)//注意j的初始值
                prime[j] = 0;
}

ps:埃克斯就是x ,鬼知道为什么我一打出来后面的就没了,加粗的p没有什么意义,只是普通的p后面就没了,有毒。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值