一个快速判断素数的方法
平常我们用暴力破解来判断n是否是素数时,都是用n试除2到√‾n判断的。但其实这中间就多了很多冗余的判断了,例如:一个数不能被2整除,那就证明了它不能被4、6、8这样的能被2整除的数整除。我们将这些冗余的数去除掉之后就能加快判断的速度。
那么,将这样的冗余的数去除之后的数会出现什么样的规律呢?我们先拿2和3来测试一下,计算一个数和前一个数的差并全部输出:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 long i, last = 7; 7 for (i = 8; i < 1000; i++) 8 { 9 if (i % 2 != 0 && i % 3 != 0) 10 { 11 printf("%d ", i - last); 12 last = i; 13 } 14 if ((i - 7) % 6 == 0) 15 printf("\n"); 16 } 17 return 0; 18 }
这个程序的运行结果为:
4 2
4 2
4 2
4 2
4 2
4 2
4 2
4 2
......
加上5之后的结果是:
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
......
加上7之后的记过是:
4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2
4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2
4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2
4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2
......
这些数在一个周期内保持一定规律,而周期则是被除数的最小公倍数。显然当使用7时,在周期内的数的规律太长了,使用5则恰到好处。
至此,我们差不多可以用代码实现了。我们知道10以内的素数是2、3、5、7,那么可以先将这些数剔除了,从大于7的数开始。先判断需计算的数能不能被2、3、5整除,然后再使用上面第二个规律,使用周期30来试除。代码实现如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int prime(long n) 5 { 6 if (n <= 5) 7 { 8 if (n == 2 || n == 3 || n == 5 || n == 7) 9 return 1; 10 return 0; 11 } 12 else 13 { 14 long s = sqrt(n), step = 7; 15 if (n % 2 == 0 || n % 3 == 0 || n % 5 == 0) 16 return 0; 17 while (step <= s) 18 { 19 if (n % step == 0) 20 return 0; 21 step += 4; 22 if (n % step == 0) 23 return 0; 24 step += 2; 25 if (n % step == 0) 26 return 0; 27 step += 4; 28 if (n % step == 0) 29 return 0; 30 step += 2; 31 if (n % step == 0) 32 return 0; 33 step += 4; 34 if (n % step == 0) 35 return 0; 36 step += 6; 37 if (n % step == 0) 38 return 0; 39 step += 2; 40 if (n % step == 0) 41 return 0; 42 step += 6; 43 } 44 } 45 return 1; 46 }
使用这个方法,程序的时间复杂度相当于暴力破解的8/30,即8*O(n)/30。

浙公网安备 33010602011771号