user-0 提问: 1468 求一个数n以内的素数个数

回复:
user: user-1
content: 引用 9 楼 sanredfish 的回复:判断一个数N是否为素数，只要判断它能否被小于N/2的素数除就可以了。而小于N/2的素数个数远小于你现在的遍历（数值越大越明显）  你的isprime函数可以这样： 建立静态一个数组，存储计算到的素数 用数组里小于N/2的所有素数依次去除N，判断是否能够整除。如果有能够整除的数，就退出返回非素数，否则返回素数。  素数数组可以在程序加载的时候计算，也可以在调用时候现算。 然后你的统计素数个数，就遍历去查这个数组就好，当一个元素刚好大于给出的n而前一个小于给出的数值n，它所在的位置i就是小于n的素数个数。  另外要注意的就是题目有没有限制输入的数据大小，如果较大需要考虑大数算法，思路还是一样的 。

user: user-1
content: 判断一个数N是否为素数，只要判断它能否被小于N/2的素数除就可以了。而小于N/2的素数个数远小于你现在的遍历（数值越大越明显）  你的isprime函数可以这样： 建立静态一个数组，存储计算到的素数 用数组里小于N/2的所有素数依次去除N，判断是否能够整除。如果有能够整除的数，就退出返回非素数，否则返回素数。  素数数组可以在程序加载的时候计算，也可以在调用时候现算。

user: user-2
content: 既然你说偶数除了2以外，都不是素数，那么就可以不判断偶数 这么写： for(i=3; i <= n; i+=2)

user: user-3
content: 看n的范围上限大不大，不大的话（在内存上限允许的情况下），考虑编译期建表 保证运行时间超短

user: user-4
content: #include <stdio.h>  int isprime(int t) {     int i;      if (t != 2 && !(t % 2))         return 0;      for(i = 2; i*i <= t; i++)         if (!(t % i))             return 0;     return 1; }   int main() {     int n,count,i;      while(scanf("%d",&n) != EOF && n) {         count = 0;         if(n <= 1) {             ;         } else {             count++;             for(i = 3; i <= n; i++)                 if(isprime(i))                     count++;         }         printf("Total prime is %d \n",count);     }     return 0; }  目前你的这个判断素数方法效率已经比较高了，减少判断的次数少于一半以上。 另外，素数一定是奇数，偶数除了2以外，没有一个是素数的。

user: user-5
content: 试了试很多年前写的代码,  求PI(2.56E11) 大约6秒,  NTH_prime(1E10) 大约1分钟 ...   #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <math.h>  #define XPREVN		(64*1024*1024)				/**/ #define XSQRTPREVN	(8*1024) #define XPREVPI		(4*1024*1024)				/* PI(XPREVN) : 3957809 */ #define XMAXNTH		((LLong)10*1000*1000*1000)	/* NTH( 1E10 ) == 252097800623 */ #define XMAXPIN		((LLong)XSQRTPREVN * XSQRTPREVN * XSQRTPREVN)  int		*X_small_prime, X_pi_small_prime; int		*X_pi_prev_N, *X_prev_V;  #define XPREVDM		(7) #define XPREVQ		(2*3*5*7*11*13*17) #define XPREVPHQ	(1*2*4*6*10*12*16)  #ifdef _MSC_VER #pragma warning( disable : 4244 ) typedef __int64		LLong; #define LLFmt		"I64d" #else typedef long long	LLong; #define LLFmt		"Ld" #endif  static LLong phiX_p(LLong x, LLong a) { 	if (a == XPREVDM) 		return x / XPREVQ * XPREVPHQ + X_prev_V[x % XPREVQ]; 	if (x < X_small_prime[a - 1]) 		return 1; 	return phiX_p(x, a - 1) - phiX_p(x / X_small_prime[a - 1], a - 1); }  LLong phiX(LLong X) { 	LLong cubeRootX, max, len3, len2, s, i, k; 	LLong sum, p; 	 	if (X <= XPREVN) 		return X_pi_prev_N[X];  	fputc('.', stderr); 	max = (LLong)(pow((double)X, 2. / 3) + 2); 	cubeRootX = (LLong)(pow((double)X, 1. / 3) + .5); 	if (cubeRootX*cubeRootX*cubeRootX > X) 		--cubeRootX; 	len3 = X_pi_prev_N[cubeRootX];  	sum = 0; s = 0; k = max - 1; 	for (i = len3; ; ++i) 	{ 		p = X_small_prime[i]; 		if (p * p > X) break;  		s += X_pi_prev_N[k] - X_pi_prev_N[(int)((double)X / p)]; 		k = (int)((double)X / p);  		sum += s; 	} 	len2 = X_pi_prev_N[p - 1];  	sum = (len2 - len3)*X_pi_prev_N[max - 1] - sum; 	sum = len3 * (len3 - 1) / 2 - len2 * (len2 - 1) / 2 + sum;  	return phiX_p(X, len3) - sum + len3 - 1; }  void initSmallPrime() { 	char *mark = (char*)calloc(1, XPREVN / 2 + 1); 	int i, j; 	X_small_prime = (int*)calloc(sizeof(int), XPREVPI); 	X_pi_prev_N = (int*)calloc(sizeof(int), XPREVN + 1); 	X_prev_V = (int*)calloc(sizeof(int), XPREVQ + 1);  	for (i = 3; i <= XSQRTPREVN; i += 2) 	{ 		if (mark[i / 2]) continue; 		for (j = i*i / 2; j <= XPREVN / 2; j += i) 			mark[j] = 1; 	} 	X_small_prime[0] = 2; 	X_pi_small_prime = 1; 	X_pi_prev_N[0] = X_pi_prev_N[1] = 0; 	X_pi_prev_N[2] = 1; 	for (i = 3; i <= XPREVN; i += 2) 	{ 		if (mark[i / 2]) 		{ 			X_pi_prev_N[i + 1] = X_pi_prev_N[i] = X_pi_prev_N[i - 1]; 		} 		else 		{ 			X_pi_prev_N[i + 1] = X_pi_prev_N[i] = 1 + X_pi_prev_N[i - 1]; 			X_small_prime[X_pi_small_prime++] = i; 		} 	} 	free(mark);  	for (i = 0; i < XPREVQ; ++i) 		X_prev_V[i] = i; 	for (i = 1; i <= XPREVDM; ++i) 		for (j = XPREVQ - 1; j >= 0; --j) 			X_prev_V[j] -= X_prev_V[j / X_small_prime[i - 1]]; }  static LLong NTH_prime_x(LLong x); LLong NTH_prime(LLong x) { 	if (x <= X_pi_small_prime) 		return X_small_prime[x - 1]; 	return NTH_prime_x(x); }  int main() { 	int j__func = 0; 	LLong a; 	clock_t now = clock(); 	initSmallPrime(); 	printf("init time cast : %lf seconds\n", (double)(clock() - now) / CLOCKS_PER_SEC);  	while (1 == scanf("%" LLFmt, &a)) 	{ 		if (a <= 0) 			break;  		if (a >= XMAXPIN) 		{ 			printf("%" LLFmt " Out of range\n", a);			 		} 		else 		{ 			if (a <= XMAXPIN) 			{ 				now = clock(); 				printf("phiX( %" LLFmt " ) == %" LLFmt "\n", a, phiX(a)); 				printf("phiX time cast : %lf seconds\n", (double)(clock() - now) / CLOCKS_PER_SEC); 			}  			if (a <= XMAXNTH) 			{ 				now = clock(); 				printf("NTH_prime( %" LLFmt " ) == %" LLFmt "\n", a, NTH_prime(a)); 				printf("NTH_prime time cast : %lf seconds\n", (double)(clock() - now) / CLOCKS_PER_SEC); 			} 		} 	}  	return 0; }  static LLong NTH_prime_helper(LLong x, LLong xMIN, LLong xMAX, LLong piMIN, LLong piMAX) { 	LLong n, piN;  	while (1) 	{ 		if (piMIN == x) 			return xMIN;  		if (xMAX - xMIN <= 2) 			return xMAX;  		n = (xMIN + xMAX) / 2 + 2 * x - piMIN - piMAX; 		n |= 1; 		if (n == xMIN) 			n += 2; 		else if (n == xMAX) 			n -= 2; 		piN = phiX(n);  		if (piN >= x) 		{ 			xMAX = n; 			piMAX = piN; 		} 		else 		{ 			xMIN = n; 			piMIN = piN; 		} 	}  	return xMAX; }  static LLong NTH_prime_get_upper(LLong x, LLong *xMIN, LLong *piMIN, LLong *piUpper) { 	LLong n = *xMIN, piN = *piMIN, xMAX, piMAX;  	while (1) 	{ 		xMAX = 1 | (LLong)(n + (x - piN + 1)*log(n)); 		piMAX = phiX(xMAX); 		if (piMAX >= x) 			break; 		n = xMAX; 		piN = piMAX; 	}  	*xMIN = n; 	*piMIN = piN; 	*piUpper = piMAX; 	return xMAX; }  static LLong NTH_prime_get_lower(LLong x, LLong *xMAX, LLong *piMAX, LLong *piLower) { 	LLong n = *xMAX, piN = *piMAX, xMIN, piMIN;  	while (1) 	{ 		xMIN = 1 | (LLong)(n + (x - piN - 1)*log(n)); 		piMIN = phiX(xMIN); 		if (piMIN < x) 			break; 		n = xMIN; 		piN = piMIN; 	}  	*xMAX = n; 	*piMAX = piN; 	*piLower = piMIN; 	return xMIN; }  static LLong NTH_prime_x(LLong x) { 	LLong initX, piINIT; 	LLong xMIN, piMIN, xMAX, piMAX;  	initX = 1 | (LLong)(1.05 * x * log(x)); 	initX |= 1; piINIT = phiX(initX);  	if (piINIT >= x) 	{ 		xMAX = initX; 		piMAX = piINIT; 		xMIN = NTH_prime_get_lower(x, &xMAX, &piMAX, &piMIN); 	} 	else 	{ 		xMIN = initX; 		piMIN = piINIT; 		xMAX = NTH_prime_get_upper(x, &xMIN, &piMIN, &piMAX); 	}  	return NTH_prime_helper(x, xMIN, xMAX, piMIN, piMAX); }

user: user-6
content: Finding prime numbers - Kenneth Haugland  Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers

user: user-5
content: 求 PI(N) 复杂度可以到 O(N^(2/3)),  现在的机器 1秒应该可以求出 100亿左右,  简单点筛法大约在 O(N*lnln(N)) ..

user: user-0
content: 这段代码系统显示时间过长，还有没有减少时间复杂度的方法，多谢指导

user: user-7
content: 筛法....