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