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