一、前提
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后面就没了,有毒。