对于12,在传统线筛素数法中,会被2*6,3*4,两组重复否定为合数。
我们可以规定每次只能让合数的质因数由大到小累计,如12=3*2*2,60=5*3*2*2。
实现时,我们可以开一个v数组,v[x]记录x的最小质因数,x能借助的素数只有prime[1]~prime[k](prime[k]<=v[x])。
在确定了为一方法枚举给个数后,这种方法就是O(N)了。
代码
例题:洛谷3383
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10000010;
int n,m,cnt;
int v[maxn],prime[maxn];
void primes()
{
cnt=0;
memset(v,0,sizeof(v));
for(int i=2;i<=n;i++)
{
if(v[i]==0)
{
prime[++cnt]=i;
v[i]=i;
}
for(int j=1;j<=cnt;j++)
{
if(i*prime[j]>n || prime[j]>v[i]) break;
v[i*prime[j]]=prime[j];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
primes();
while(m--)
{
int x;
scanf("%d",&x);
if(v[x]==x) puts("Yes");
else puts("No");
}
return 0;
}