Fork me on 
Catalogue

我自问酒不问仙,半世逍遥半世癫,我自问心不问佛,半世情愁半世痴。 ​​​​

(数论基础)线性筛の小小讲解

    思想:

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

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

posted @ 2020-10-22 17:11  汉孤臣  阅读(170)  评论(0)    收藏  举报
Live2D