傳送門 思路
使用傳說中的區間埃式篩。
可以知道,如果 [l
,r] [l,
r]
中的某個數是合數,那麼它的乙個質因子一定 ≤r
√ ≤
r。所以可以使用埃式篩先篩出 [1
,r√]
[ 1,
r]
的所有素數,再用這些素數去篩區間中的合數。
雖然按道理尤拉篩比埃式篩在第一步中時間複雜度更佔優勢,但是第一步最多隻會算到四萬多,尤拉篩常數較大,反而比較慢。
第二步只能用埃式篩。
參考**
關鍵**是unsigned int j = prime[i] * std::max(2, ((l + prime[i] - 1) / prime[i]));
,要注意型別。
尤拉篩
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef
int int;
using
std::cin;
using
std::cout;
using
std::endl;
int readin()
while (ch >= '0' && ch <= '9')
if (minus) a = -a;
return a;
}void printout(int x)
dowhile (x);
dowhile (length);
}const
int maxn = int(1e6) + 5;
int l, r;
const
int maxm = 46340;
int prime[maxm];
bool isntprime[maxm];
int sqrtr;
void init()
}}bool is[maxn];
void run()
int main()
埃式篩#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef
int int;
using
std::cin;
using
std::cout;
using
std::endl;
int readin()
while (ch >= '0' && ch <= '9')
if (minus) a = -a;
return a;
}void printout(int x)
dowhile (x);
dowhile (length);
}const
int maxn = int(1e6) + 5;
int l, r;
const
int maxm = 46340;
int sqrtr;
bool isntprime1[maxm];
bool isntprime2[maxn];
void run()
}int ans = 0;
for (int i = 0, to = r - l + 1; i < to; i++)
ans += !isntprime2[i];
printout(ans);
}int main()
P1835 素數密度 尤拉篩 埃氏篩法
題目描述 給定區間 l,r l r 2147483647,r l 1000000 請計算區間中素數的個數。輸入格式 兩個數l和r。輸出格式 一行,區間中素數的個數。輸入輸出樣例 輸入 1 2 11 輸出 1 此題有乙個坑。若乙個數是int max,看起來用int是可以的。但若是把這個數 1了呢?in...
素數密度 Standard IO
description 給定區間 l,r l r 2147483647,r l 1000000 請計算區間中素數的個數。input 兩個數l和r output 一行,區間中素數的個數。題解看到題目,很水啊。但一看到l,r的範圍,太恐怖了!資料範圍之大,所以不能乙個乙個列舉,用篩素來快速求出素數。因為...
洛谷p1835 素數密度 (線性尤拉篩,埃式篩)
題目分析 難度 普及 提高 暴力40分做法 從l到r進行列舉,然後判斷是否為素數!但這樣顯然是不對的,要結合篩法來解決此題,雖然l,r的範圍是整個int的取值,但是兩者的差值為1e6,可以從此突破!預備知識 解決乙個問題 求出不大於n的素數的個數 樸素篩法 時間複雜度 o n根號n 普通樸素演算法 ...