【题目描述】
编程求2~n(n为大于2的正整数)中有多少个素数。
【输入描述】
输入n (2<= n <=50000)
【输出描述】
素数个数
【输入样例】
10
【输出样例】
4
#include<iostream> #include<cmath> using namespace std; bool judge(int x); int main() { int n; int i; int sum=0; cin>>n; for(i=2; i<=n; i++) if(judge(i))//若是素数 sum++;//累加素数个数 cout<<sum<<endl; return 0; } bool judge(int x)//判断素数 { int i=2; while(i<=floor(sqrt(x))&&(x%i)!=0) i++; if(i>floor(sqrt(x))) return true; return false; } // 判断素数的几种方式 // 1 定义法(除了1和他本身之外,没有任何一个数能被整除)(试除法) bool is_prime3(unsigned long long n) { //slow for (int i = 2; i < n - 1; i++) { if (n % i == 0) { return 0; } } return 1; } // 2. 改进 /* 根据如果一个数是合数,那么它的最小质因数肯定小于等于它的平方根。 用反证法可以证明一下。假设x是n的最小质因数,则存在n/x=p。p>x,x*p=n。如果x不小于等于它的平方根,则x*x>n,而p>x,故x*p>n,假设不成立。合数是与质数相对应的自然数。一个大于1的自然数如果它不是合数,则它是质数。也就是说如果一个数能被它的最小质因数整除的话,那它肯定是合数,即不是质数。所以判断一个数是否是质数,只需判断它是否能被小于它开跟号后的所有数整除,因此,这样做的运算少了很多,降低了时间复杂度。 */ int isprime(int m) { int i; for(i=2;i<=sqrt(m);i++) /*sqrt(int n)这个函数需要引入math.h头文件*/ if(m%i==0) return 0; else return 1; } // 3 查表法 // 4.孪生素数 /* 孪生素数: 所谓孪生素数指的是间隔为 2 的相邻素数,它们之间的距离已经近得不能再近了。 若n≥6且n-1和n+1为孪生素数,那么n一定是6的倍数。 证明: ∵ n-1和n+1是素数 ┈┈┈┈┈ ① ∴ n-1和n+1是奇数 ∴ n是偶数,即n是2的倍数 ┈┈┈┈┈ ② 假设n不是3的倍数,得: n=3x+1 或 n=3x+2, 如果n=3x+1,则n-1=3x,与①违背,故n≠3x+1; 如果n=3x+2,则n+1=3(x+1),与①违背,故n≠3x+2; ∴假设不成立,即n是3的倍数,又有②得结论: n是6的倍数。 由上面的规律可以推出下面结论: 若x≧1且n=6x-1或n=6x+1不是素数,那么n一定不是2和3的倍数。 证明: ∵n=6x-1或n=6x+1,即n=2(3x)-1或n=2(3x)+1或n=3(2x)-1或n=3(2x)+1。 ∴n一定不是2和3的倍数。 素数出现规律: 当n≧5时,如果n为素数,那么n mod 6 = 1 或 n mod 6 = 5,即n一定出现在6x(x≥1)两侧。 证明: 当x≥1时,有如下表示方法: ┈┈ 6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1┈┈ 不在6x两侧的数为6x+2,6x+3,6x+4,即2(3x+1),3(2x+1),2(3x+2),它们一定不是素数,所以素数一定出现在6x的两侧。 */ bool isPrime(int num) { if (num == 2 || num == 3) return true; if (num % 6 != 1 && num % 6 != 5) return false; for (int i = 5; i*i <= num; i += 6) if (num % i == 0 || num % (i+2) == 0) return false; return true; }
返回目录:题解目录