先理解几个结论
①任何一个数n都可以表示成素数的乘积。对于素数来说显然成立;而合数可一分解为两个大于1的数m1和m2相乘,若m1、m2之中有合数,那么将其继续分解为两个大于1的数m1和m2相乘,重复这一步骤,最后一定可以将n分解成若干素数的乘积,这若干素数称为n的素因数。将n的全部素因数按升序排列为p1,p2,…,pk,则n=p1.p2…pk=p1.m(m=p2…pk),于是有
②任何一个合数都可以表示为其最小素因数与一个大于1的数相乘,反之必为素数。
③显然第一个最小素因数为p的合数是p的平方。
④设N以内所有素数按升序排列为p1,p2,…,pk,由①、②、③,N以内的所有合数,可按最小素因数将所有合数分为k类,第一类是最小素因数为p1的合数,第二类是最小素因数为p2的合数,依次类推。那么,N以内的所有合数为p1.(p1+0),p1.(p1+1),…,p1.(p1+a1),p2.(p2+0),p2.(p2+1),…,p2.(p2+a2),…,pk.(pk+0),pk.(pk+1),…,pk.(pk+ak)。其中pi.(pi+ai)<=N。
若n未被2至n-1的素数筛除,则必定为素数。
#include <iostream>
using namespace std;
const long long int N = 1e8;
long long cnt = 0,vis[N]={0},prim[N]={0};
void primeTable()//筛选出所有素数,存入prim数组
{
for(long long i = 2; i<=N; i++)
{
if(!vis[i])//合数标记为1,任何一个合数n都可表示为小于n的素数p的k倍,即n = k*p, k<=n, p<=n;
{
prim[++cnt] = i;
}
for(long long j = 1; j<=cnt; j++)
{
long long t = i*prim[j];//筛选出最小素因数为prim[j]这一类的合数
if(t>N)
break;
vis[t] = 1;//素数的倍数标记为合数
if(!(i%prim[j]))
{
/******************************************
若i整除prim[j],则 prim[j]是i的因数,
且是最小素因数(prim[]中素数按升序排列),
i*prim[j+1]...i*prim[j+a](j+a<=cnt)都是
最小素因数为prim[j] 这一类的合数,因此无需重复标记。
*******************************************/
break;
}
}
}
}
int main(){
long long n;
primeTable();
while(cin>>n)
{
long long i = 1;
cout<<n<<"以内的所有素数:";
while(prim[i]<=n)//打印n以内的所有素数
{
cout<<prim[i++]<<" ";
}
cout<<endl<<"共计"<<i-1<<"个"<<endl;
}
return 0;
}