(数论基础)线性筛の小小讲解
思想:
众所周知,唯一分解定理:N= p1^c1*p2^c2*p3^c3*...*pm^cm。
于是每个合数都能用若干个素数相乘表示。而素数只有一个素数因数。只要一个数存在不等于自身的素数因数,就必定是合数,反之,为素数。
代码思路:
我们可以将每个数(包括素数合数)向外扩展一次(用一个素数×该数),只要经拓展就必定有两个或以上的质因数,就一定是合数,用数组记录他最小质因数。
而向外扩展不能让数组越界,如果越界,要立即跳出循环。
于是我们用v记录他们的最小因数(除去1)。最小质因数为自身的一定是质数。
而向外扩展的过程仅涉及不大于最小质因数,又可以避免12=4*3与12=6*2重复的现象,正好可以从大到小列举所有质因数而不发生计算的重复,可以有效节省时间。时间复杂度为O(n)。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn=5000000+50; int n,m,ans,v[maxn],cnt,p[maxn]; int main() { for (int i=2; i<=maxn-50; i++) { if (!v[i]) p[++cnt]=i,v[i]=i; for (int j=1; j<=cnt; j++) if (p[j]<=v[i] && i*p[j]<=maxn-50) v[i*p[j]]=p[j]; else break; } v[0]=1;//令0不是素数 while (scanf("%d",&n)!=EOF) { if (v[n]==n) printf("Yes\n"); else printf("No\n"); } return 0; }

浙公网安备 33010602011771号