(數論基礎)線性篩の小小講解
阿新 • • 發佈:2020-10-22
思想:
眾所周知,唯一分解定理:N= p1^c1*p2^c2*p3^c3*...*pm^cm。
於是每個合數都能用若干個素數相乘表示。而素數只有一個素數因數。只要一個數存在不等於自身的素數因數,就必定是合數,反之,為素數。
程式碼思路:
我們可以將每個數(包括素數合數)向外擴充套件(用一個素數×該數),只要經拓展就必定有兩個或以上的質因數,就一定是合數。
於是我們用v記錄他們的最小因數(除去1)。
而向外擴充套件的過程僅涉及不大於最小質因數,又可以避免6=3*2與6=2*3重複的現象,正好可以從大到小列舉所有質因數而不發生計算的重複,可以有效節省時間。時間複雜度為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; }