【數論】埃氏篩法&&CODE[VS] 3223 素數密度 = =

DQS真是太神辣!
學長博客地址:http://blog.csdn.net/loi_dqs/article/details/49486467(點擊進入異♂世界)

埃氏篩法:

時間複雜度O(nloglogn)
(mdCSDN分分鐘崩潰,重寫第四次QAQ)
想要得到n以內所有質數,應篩去sqrt(n)以內的所有質數的倍數
爲什麼呢
因爲,我們假設a = sqrt(n),所以有a^2 == n,因此一個自然數的因數,如果大於sqrt(n),則必定有一個因數是小於sqrt(n)的,反之亦然,所以只需要找到小於等於sqrt(n)的質數即可,減少了運算次數,提高了效率。

對於3223,這個題,一個問題就是l,r範圍有點大,直接用數組存肯定會炸掉,所以我們就不存了!!!,直接在sqrt(n)以內篩出質數,再用篩出來的質數在區間[l,r]中篩出合數。
這裏我們讓j = max(2,(l+i-1)/i)*i,作爲枚舉的下界,(i是你之前所篩出的一個質數),之所以在2與(l+i-1)/i之間取max,是因爲2是最小的質數同時也是普遍i的最小倍數(因爲i*1沒必要舉到),一定不能小於2,而(l+i-1)/i則是大於等於l的i的最小倍數,這麼做的話是可以減少運算步數,最後將這個倍數乘以i本身,再在循環的時候,每次加i,就可以很快地找出合數了

還有就是在用質數篩合數的時候,別忘了在2後加上 -ll後綴,2ll表示long long型的常數2

垃圾題代碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

const long long maxn = 1233333;

using namespace std;
typedef long long LL;

LL l,r;
LL ans;
LL n;
bool pri[maxn];
bool check[maxn];

LL read()
{
    char ch;
    LL data = 0;
    LL f = 1;
    while(ch <'0'|| ch >'9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();

    }
    do{
        data = data*10+ch-'0';
        ch = getchar();
    }while(ch >='0'&&ch <='9');
    data *= f;
return data;
}

inline void prime(LL x)
{
    memset(check,0,sizeof(check));
    for(LL i = 2;i <= sqrt(x);i++)
    {
        if(check[i] != 1)
        {
            for(LL j = i*i;j <= sqrt(x);j += i)
            {
                check[j] = 1;
            }
            for(LL j=max(2ll,(l+i-1)/i)*i;j<=r;j+=i) 
            {
                pri[j-l]=1;
            }
        } 
    }
}

int main()
{
    l = read();
    r = read();
    prime(r);
    for(LL i = 0;i <= r - l;i++)
        if(!pri[i]) 
            ans++;
    printf("%lld\n",ans);
return 0;
}

THE END

By Peacefuldoge
http://blog.csdn.net/loi_peacefuldog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章