から Wikipedia:
アルゴリズムの複雑さは
O(n(logn)(loglogn))
ビット操作です。
どうやってそこに着きますか?
複雑さがloglogn
の用語を含むことは、どこかにsqrt(n)
があることを示しています。
最初の100個の数字(n = 100
)でふるいを実行していると仮定します。数字を複合としてマークするのに一定の時間がかかると仮定すると(配列の実装)、mark_composite()
を使用する回数は
n/2 + n/3 + n/5 + n/7 + ... + n/97 = O(n^2)
そして、次の素数を見つけるために(たとえば、7
の倍数であるすべての数を消した後に5
にジャンプするため)、操作の数はO(n)
になります。
したがって、複雑さはO(n^3)
になります。 同意しますか?
項の数が一定ではないため、n/2 + n/3 + n/5 +…n/97はO(n)ではありません。 [編集後の編集:O(n2)緩い上限は。]緩い上限はn(1 + 1/2 + 1/3 + 1/4 + 1/5 + 1/6 +…1/n)(-の逆数の合計all最大n)までの数字、これはO(n log n)です- 調和数 を参照してください。より適切な上限はn(1/2 + 1/3 + 1/5 + 1/7 +…)、つまりnまでの素数の逆数の合計、つまりO(n log log n)です。 ( here または here を参照してください。)
「次の素数を見つける」ビットはO(n)全体、 amortized — total 、ステップごとではないため、アルゴリズムのこの部分はO(n)のみを取ります。
したがって、これら2つを使用すると、O(n log log n)+ O(n) = O(n log log n)算術演算の上限が得られます。ビット演算をカウントする場合、 'nまでの数を処理しているので、それらは約log nビットを持ちます。これは、log nの係数が入る場所で、O(n log n log log n)ビット操作を与えます。
n/i
_ステップを実行します。ここで、i
は素数=>全体の複雑さはsum(n/i) = n * sum(1/i)
です。素調和列によると、i
が素数であるsum (1/i)
はlog (log n)
です。合計で、O(n*log(log n))
。上のループはn
をsqrt(n)
に置き換えることで最適化できると思うので、全体的な時間の複雑さはO(sqrt(n)loglog(n))
になります。
_void isprime(int n)
{
int prime[n],i,j,count1=0;
for(i=0;i<n;i++)
{
prime[i]=1;
}
prime[0]=prime[1]=0;
for(i=2;i<=n;i++)
{
if(prime[i]==1)
{
printf("%d ",i);
for(j=2;(i*j)<=n;j++)
prime[i*j]=0;
}
}
}
_
複雑度にloglognの用語が含まれていることは、どこかにsqrt(n)があることを示しています。
ふるい分け中に素数P
を見つけた場合、現在の位置+ P
で数字の交差を開始しないことに注意してください。実際にP^2
で数字の交差を開始します。 P^2
より小さいP
のすべての倍数は、以前の素数で相殺されます。
上記の説明を参照してください。内側のループは、sqrt(n)までのすべての素数の調和和です。したがって、実際の複雑さはO(sqrt(n)* log(log(sqrt(n))))です