クラシック:
INT isprime(INT N)
{
int型のI。
もし(N <= 1)戻り 0 ;
以下のための(I = 2 ; I <= SQRT(N)、iは++ )
場合(N%I == 0)戻り 0 ;
リターン 1 ;
}
もちろん、あなたが特定の範囲内の素数を決定したい場合は、このアルゴリズムは非常に遅いです。
エラトステネス(エラトステネス)ふるいです
INTのフラグ[MAXN + 5 ] = { 1、1 }。 // (フラグ[I] = 0)iは为素数であれば
ボイドisprime()
{
int型Iを、J。
memset(フラグ、0、はsizeof (フラグ))。
ため(I = 2 ; iが<= SQRT(N)、iは++ )
{
場合(!フラグ[I])
{
ため(J =私は*; J <= N; J + = I)
フラグ[J] = 1 。
}
}
}
オイラー(オイラー)ふるいです
INTのフラグ[MAXN + 5 ] = { 1、1 }、プライム[MAXN + 5 ]。 // 場合(フラグ[I] = 0)I为素数
ボイドisprime()
{
int型 I、J、CNT = 0 。
memset(フラグ、0、はsizeof (フラグ))。
以下のための(I = 2 ; I <= MAXN; iは++ )
{
もしプライム[CNT ++] =(フラグ[i]が!)I。
用(J = 0 ; J <CNT &&プライム[J] * I <= MAXN J ++ )
{
フラグ[プライム[J] * I] = 1 。
もし(I%、プライム[J] ==0)ブレーク。
}
}
}
なぜとき|ときプライム[j]は、蚊帳の外になりますか?
、私はそのので|プライム[j]は、Mを= 、 私が総理[J + 1] kで求めることができる「*プライム[J]、およびのでプライム[J + 1]>プライム*ていることが分かる 、[j]をので、その時点で、kは」私よりも確かに大きい、それは将来的に更新することができるI *プライム[J + 1]は、ダブルカウントを避けるために、この時点で行ってください。
インターバル素数のふるいです
引用:整数aとbのを考えると、私は区間[a、b)はどのように多くの素数を求めることができますか?(A <b≤10^ 12、B
がNの約数がN / D次いで、あるN Nの約数である場合に= N×dのための素因数の最小数は√bのB、D内の係合を超えてはならないので、D /分(D、Nを理解/ D)≤√n。
素数テーブルを√N未満である場合、それは式[A、B)上のオングストローム篩に使用することができます。すなわち、各ウェルの[2、√b)テーブルと[B)し、[2、表素数を篩い分け√b)だけでなく、からその倍数からテーブル[し、ありますB)テーブルのフィルタリングは、最後に残った素数間隔は[A、B)です。
場合は区間における要件[1E ^ 9,1e ^ 9 + 2)素数は、我々はそれを^ 9 + 3サイズの配列1Eを開くしようとしていますか?実際に、私たちは宇宙のオーバーヘッドを減らすことができますオフセットの添字を使用し、使用しないでください。左1E ^ 9にオフセット[1E ^ 9,1e ^ 9 + 2)[0,2に対応)を、全区間についてです。
はっきり、それを使用することで知られている小さな素数が素数の未知の広い範囲を更新し、インデックスオフセットメンテナンス間隔を使用します。
#include <ビット/ STDC ++ H.>
使用して 名前空間STD;
typedefの長い ロングLL;
のconst int型 MAXN = 1E5;
BOOL is_prime [MAXN]、is_prime_small [MAXN];
LLプライム[MAXN]、prime_num = 0 ;
// 間隔の[ iが素数で表されるふるい方法を実行する)の整数で、is_primeは、[IA]真= <=> bがA、(オフセット添字a)の
ボイドsegment_sieve(LL、BのLL)
{
ため(I LL = 0 ;私* IはBを<; I ++)は、[I]は= is_prime_small trueに ; // [2に、SQRT(B))が初期化され、すべての素数である
ため(LL I = 0 ; I <BA; I ++)はis_prime [I]は= trueに、//初期化されている[シフト後、Bの添え字)に
するための LL = I(2 I ++)は、私はBを<*; // フィルタ[2、SQRT(B))
{
IF )[I]をis_prime_small(
{
用(LL J = 2 * I; J * J <B; = J + I)
is_prime_small [J]は = falseに;
// (1-A + I)/ I iは、I 2の最小の最も近い倍数である与えます倍、次いでスクリーニング
するため(LL J = MAX(2LL、(A + I- 1)/ I)は、Iは*; J <B; = J + I)
is_prime [J -a] = falseに;
}
}
のための(I = LL 0 ; I <BA; Iは++)// オフセットインデックスの数カウント
IF )(is_prime [I]を
プライム[prime_num ++] =私は+ 。
}
int型のmain()
{
LL、B。
一方、(〜のscanf(" %のLLDの%のLLD "、&、&B))
{
prime_num = 0 。
memsetの(プライム、0、はsizeof (プライム));
segment_sieve(B)
printf(" %LLDする\ n " 、prime_num)。
}
戻り 0 。
}