1. 程式人生 > 實用技巧 >(數論基礎)線性篩の小小講解

(數論基礎)線性篩の小小講解

思想:

眾所周知,唯一分解定理: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; }

例題:https://vjudge.net/problem/NBUT-1151