By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10 001st prime number?
static void Main(string[] args) { long startTime, endTime; Int64 i=1; int k=1; startTime = DateTime.Now.Ticks; while (k < 10001) { i += 2; if (isPrime(i) == true) k++; } endTime = DateTime.Now.Ticks; Console.WriteLine("result:{0} run time:{1} ms",i,(endTime-startTime)/10000.0); Console.ReadLine(); } public static bool isPrime(Int64 n) { Int64 max = (long)Math.Sqrt(n); for (Int64 i = 2; i <= max; i++) { if (n % i == 0) return false; } return true; }
结果:104743,执行时间基本在64ms,有时候一个小的改进对算法的执行也有很大的影响。把素数判断函数里的开根号函数在循环之前做,速度几乎快了1倍。
上述写法很传统。也不知道其他更好的方法。期待指点。
下边是高手的写法:
依据:任何一个大于3的质数加一或减一必然是6的倍数
解答:
1.每三个连续的数之中必有一个是3倍数。
2.设这个质数叫a,a肯定是不为3的倍数的奇数(因为是个质数)。
3.那么a-1,a+1其中必有1个是3的倍数。
4.同时,a-1和a+1都是偶数 即2的倍数。(因为每二个连续的数之中必有一个是2倍数).
5.所以a-1和a+1其中必有一个为2的倍数且为3的倍数的,即有6的倍数的数。
6.因此。a必然是6的倍数加一或减一的数。
代码:
static void Main(string[] args) { long startTime, endTime; startTime = DateTime.Now.Ticks; int i=3, n=1, s=1,r,x=0,p,t; while (i <= 10001) { if (s == 1) { x = 6 * n - 1; s = 0; } else { x = 6 * n + 1; s = 1; n = n + 1; } r = (int)Math.Sqrt(x); p = 1; t = 3; while(t<=r) { if (x % t == 0) { p = 0; break; } t = t + 2; } if (p == 1) i = i + 1; } endTime = DateTime.Now.Ticks; Console.WriteLine("result:{0} run time:{1} ms",x,(endTime-startTime)/10000.0); Console.ReadLine(); }
判读素数的过程从3开始到平方根之间的奇数,因为奇数不可能被偶数整除。速度整整比一开始的程序快了3倍多。只要20多ms.
Using numbers of the form 6k±1 is certainly one of the most efficient approaches for an unknown upper limit; that is, continuing through good "prime candidates" until you arrive at the nth prime.
You got me thinking... with a problem like this, I wonder how many of us used the principle of the Sieve of Eratosthenes? In fact, it is neither the best nor a legitimate approach when the upper limit is unknown.
<u>The Method</u>
Set up an array with the second and all odd elements as "prime candidates". The systematically work through the odds, starting at the the 3rd element, until you find a "prime candidate", p. Mark this element as prime, then unmark all multiples of p, as they cannot be prime. For example, once it arrives at 7 (which will not have been cancelled out by 3 or 5), we unmark 14, 21, 28, 35, ... But you will notice that every other element is even (2p, 4p, 6p, ...), and we never marked them initially as "prime candidates". So we can start at 3p and skip through in multiples of 2p. Once this is done, if p(k) is true we have a prime, so a count through the array will locate the 10001st prime. At the bottom of the post is a BASIC implementation to find all primes up to one million.
<u>The Problem</u>
As explained above, this assumes that the 10001st prime is found below one million, and it would have failed if it was above one million. However, it occurs at 104743 and, although it did find the answer (we were lucky), it turned out to be unnecessary to work out ALL the primes below one million (making it inefficient)!?!
I wonder how many people used this BAD method to solve the problem? I did! :blush:
<u>An Implementation</u>
Dim p(1000000) As Boolean Dim a, t, max As Long max = 1000000 p(2) = True For a = 3 To max Step 2 p(a) = True Next a t = 3 Do For a = 3 * t To max Step 2 * t p(a) = False Next a t = t + 2 Loop Until t >= max t = 1 a = 1 Do t = t + 2 If p(t) Then a = a + 1: List1.AddItem t Loop Until a = 10001 MsgBox (t)