当前位置: 代码迷 >> 综合 >> 【PAT】1007 review
  详细解决方案

【PAT】1007 review

热度:27   发布时间:2023-12-05 22:59:18.0

int i;for(i=0; ;) 与 for(int i=0 ; ;) 两种定义循环变量的方式的区别:

the difference between int i;for(i = 0;;) and for(int i = 0;;):

  • 两种均可,前者i在for循环外部定义,则i的值在程序未结束之前就一直存在,i所占的内存空间直到程序结束时才释放;后者的i在for循环内部定义,则当for循环结束时,i所占的内存空间就被释放了。一般建议用后者的方式,因为当程序较大时,前者更占内存,这样程序在运行时CPU的负担就更大,内存溢出的风险更大。

————————————————————————————————————————

Main Problem:PAT 1007
Keywords:prime;twin prime(孪生素数)
three methods to judge a number is a prime or not

	1   这里特殊处理了一下小于等于3的数,因为小于等于3的自然数只有2和3是质数。然后,我们只需要从2开始,一直到小于其自身,依次判断能否被n整除即可,能够整除则不是质数,否则是质数。
public static boolean isPrime(int n){
    if (n <= 3) {
    return n > 1;}for(int i = 2; i < n; i++){
    if (n % i == 0) {
    return false;}}return true;
  1. 假如n是合数,必然存在非1的两个约数p1和p2,其中p1<=sqrt(n),p2>=sqrt(n)。由此我们可以改进上述方法优化循环次数。如下:
public static boolean isPrime(int n) {
    if (n <= 3) {
    return n > 1;}int sqrt = (int)Math.sqrt(n);for (int i = 2; i <= sqrt; i++) {
    if(n % i == 0) {
    return false;}}return true;
}

3质数还有一个特点,就是它总是等于 6x-1 或者 6x+1,其中 x 是大于等于1的自然数。
相关定理证明:
定理1:当n≥5时,如果n为素数,那么n%6=1或n%6=5。即n一定出现在6x(x≥1)的两侧。
证明:当x≥1时,有如下表示方法:

  ……   6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1   ……      

观察得,当n≥5时,不在6x(x≥1)两侧的数为6x+2,6x+3,6x+4,……,即2(3x+1),3(2x+1),2(3x+2)……。

显然,它们一定不是素数。
所以当n≥5时,素数一定出现在6x(x≥1)的两侧。

这里要注意的是,不在6x(x≥1)两侧的肯定不是素数,但在6x(x≥1)两侧的并不是一定就是素数。

所以此时需要对6x(x≥1)两侧数据进行判断。常见方法是采用普通sqrt(n)版判断素数方法(步长取6)。

定理2:若n≥6且n-1和n+1为孪生素数,那么n一定是6的倍数。

证明:所谓孪生素数指的是间隔为2的相邻素数。

∵ 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-1是偶数的可能,与①违背,故n≠3x+1;

如果n=3x+2,则n+1=3(x+1),此式存在n+1是偶数的可能,与①违背,故n≠3x+2;

∴n不是3的倍数的假设不成立,故得n是3的倍数,又结合②得结论:

n是6的倍数。

public static boolean isPrime(int num) {
    if (num <= 3) {
    return num > 1;}// 不在6的倍数两侧的一定不是质数if (num % 6 != 1 && num % 6 != 5) {
    return false;}int sqrt = (int) Math.sqrt(num);for (int i = 5; i <= sqrt; i += 6) {
    if (num % i == 0 || num % (i + 2) == 0) {
    return false;}}return true;
}

To be resolved problems:

  • int 4 bytes (32 bits) - count primes among [0,2312^{31}231-1] and print
    them out.
  • long long 8 bytes(64bits) - count primes among [0,2642^{64}264-1] and
    print them out.

Original AC Code:2021年6月4日11:00:40

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define M 100000
bool isprime( int  number)
{
    if(number==1) return false;if(number==2||number ==3)  return true;else{
    for(int i = 2  ; i <= sqrt(number) ; i ++){
    if(number%i == 0 ) return false;}}return true;
}
int main()
{
    int n;cin>>n;int j=0;int prime[M];int count = 0 ;memset(prime,0,M*sizeof(int));for(int i  = 1 ;i <n+1 ;i ++){
    if(isprime(i)){
    prime[j++]=i;// cout<<i<<endl;}}for(int k = 1;k < j ; k ++ ){
    if(prime[k]-prime[k-1]==2)count ++;}cout<<count<<endl;return 0 ;
}

————————————————
版权声明:本文部分内容来自 CSDN博主「hnjzsyjyj」、阿飞__的原创文章,遵循CC 4.0 BY-SA版权协议。
博主「hnjzsyjyj」原文链接:https://blog.csdn.net/hnjzsyjyj/article/details/101234139

博主 阿飞__原文链接:https://blog.csdn.net/afei__/article/details/80638460

  相关解决方案