首页 > 试题广场 >

求素数

[编程题]求素数
  • 热度指数:3307 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
输入M、N,1 < M < N < 1000000,求区间[M,N]内的所有素数的个数。素数定义:除了1以外,只能被1和自己整除的自然数称为素数

输入描述:
两个整数M,N


输出描述:
区间内素数的个数
示例1

输入

2 10

输出

4

python解法

使用埃拉托斯特尼筛法

基本思想:素数的倍数一定不是素数
实现方法:用一个长度为N+1的数组保存信息(0表示素数,1表示非素数),先假设所有的数都是素数(初始化为0),从第一个素数2开始,把2的倍数都标记为非素数(置为1),一直到大于N;然后进行下一趟,找到2后面的下一个素数3,进行同样的处理,直到最后,数组中依然为0的数即为素数。
如果n*n > 范围最大值就跳出。

import math


def count_prime(N):
    n = int(math.sqrt(N) + 1)
    arr = [True] * (N + 1)
    for i in range(2, n):
        for j in range(2, N):
            if i * j <= N:
                arr[i * j] = False
            else:
                break
    return sum(arr) - 2


start, end = map(int, input().split())
print(count_prime(end) - count_prime(start - 1))

要注意start要减去1。

发表于 2019-02-24 19:30:05 回复(1)
更多回答
def primeNum(m, n): # 正面思路时间复杂度不过关
    res = 0
    for i in range(m, n+1):
        for j in range(2, int(i**0.5)+1):
            if i%j == 0:
                break
        else:
            res += 1
    return res

def prime(n):    # 类似动态规划的思想
    res = [1]*(n+1)
    for i in range(2, int(n**0.5)+1):     # n**0.5可能不是int类型,注意
        for j in range(2, n):
            if i*j <= n:
                res[i*j] = 0         # 不是素数
            else:
                break
    return sum(res)

if __name__ == "__main__":
    m, n = map(int, input().split())
    print(prime(n) - prime(m-1))   # 注意包括边界

发表于 2019-03-25 15:57:27 回复(0)
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;
int main(){
    int count=0;
    int M;
    int N;
    cin >> M;
    cin >> N;
    int flag=0;
    for(int i=M; i<=N; i++){
        flag=0;
        for(int j=2; j <= sqrt(i); j++){
            if(i%j==0){
                flag=1;
                break;
            }
        }
        if(flag==0){
                count++;
            }
    }
    cout << count;
    return 0;
}

发表于 2019-03-02 20:49:03 回复(0)
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int m=sc.nextInt();
        int n=sc.nextInt();
       if(n>m) {
           int temp =m;
           m=n;
           n=temp;
       }
        int count=0;
        for(int i = n;i<=m;i++){
            if(Main.issushu(i))
                count++;
        }
        System.out.println(count);
    }
    public static boolean issushu(int t){
        boolean flag = true;
       
        for(int i=2;i<=Math.sqrt(t);i++){
            if(t%i==0){
             flag = false;
                break;
            }
           
        }
           return flag; 
    }
}
发表于 2019-01-16 14:27:22 回复(0)
#include <bits/stdc++.h>
using namespace std;

bool isPrime(int n)   //判断一个数是否为素数
{
    if(n<=1)
    {
        return false;
    }
    else
    {
        for (int i = 2; i <= sqrt(n); i++)
        {
            if(n%i == 0)
            {
                return false;
            }
        }
        return true;
    }
}

int main()
{
    int M,N;
    cin >> M >> N;
    int cnt = 0;   //记录区间内素数的个数
    for(int i = M; i <= N; i++)
    {
        if(isPrime(i))   
        {
            cnt++;
        }
    }
    cout << cnt << endl;
    return 0;
}

发表于 2019-01-10 13:15:19 回复(0)
// 这个题自测有问题,自己输入2 10 正确答案是4,他给人报错为2
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int start = scanner.nextInt();
        int end = scanner.nextInt();
//        System.out.println(violence(start,end));
//         System.out.println(violence2(start,end));
         System.out.println(ethiopia(start,end));
    }
    /**
     * 方法一、暴力破解法-1
     * 从起始数开始循环到终止数,2~当前数-1,不可整除为素数
     * 是进行count++
     * 结果为:超时,算法复杂度过大
     * */
    private static int violence(int start,int end){
        int count = 0;
        for (int i = start; i < end; i++) {
            if (i == 2){
                count++;
            }
            for (int j = start; j < i; j++) {
                if (i%j == 0){
                    break;
                }
                if (j == i-1)
                    count++;
            }
        }
        return count;
    }
    /**
     * 方法二、暴力破解法-2
     * 从起始数开始循环到终止数,设boolean标志,判断当前数是否是素数
     * 是进行count++
     * */
    private static int violence2(int start,int end){
        int count = 0;
        for (int i = start; i < end; i++) {
            count += isPrime(i) ? 1 : 0;
        }
        return count;
    }

    private static boolean isPrime(int i) {
        for (int j = 2; j <= Math.sqrt(i); j++) {
            if (i % j == 0){
                return false;
            }
        }
        return true;
    }
    /**
     * 方法三、埃塞法
     * 初始化标志位boolean数组,全为false 代表是素数
     * 先判断一下,flag 为false 代表素数,count++
     * 素数的倍数都不是素数,将其标志为 true
     * */
    private static int ethiopia(int start,int end){
        int count = 0;
        boolean[] flag = new boolean[end];

        for (int i = start; i < end; i++) {
            if (!flag[i]){
                count++;
                // System.out.println(i);
                // 注意:在使用 j = i * i 可减少查找次数,但容易造成数组越界
                for (int j = i * 2; j < end; j+=i) {
                    flag[j] = true;
                }
            }
        }
        return count;
    }
    
}

发表于 2022-01-24 12:55:02 回复(0)
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int m,n,sum=0;cin>>m>>n;
    for(int i=m;i<=n;i++)
    {
        int flag=0;
        for(int j=2;j*j<=i;j++)
            if(i%j==0)    {flag=1;break;}
        if(!flag) sum++;
    }
    cout<<sum;
}


发表于 2022-01-24 04:52:27 回复(0)
#include<iostream>
#include<cmath>
bool isPrime(long i)
{
    if(i==2)return true;
    else
    {
         for(int j=2;j<=sqrt(i);j++)
    {
        if(i%j==0)return false;
    }
    }
   
    return true;
}
int main()
{
    long M,N;
    while(std::cin>>M>>N)
    {
        int count=0;
        for(long i=M;i<=N;i++)
        {
            if(isPrime(i))count++;
        }
        std::cout<<count<<std::endl;
    }
    return 0;
}
发表于 2020-09-17 23:21:14 回复(0)
c++ 埃拉算法   本题由于数据在100000级别 其实 使用 sqrt() 也好 n/2 也好都是无法通过的。
但是牛客的oj用例似乎一直很有问题,建议大家去leetcode查找此题。
#include<bits/stdc++.h>
using namespace std;

int main(){
    int m,n;
    while(cin>>m>>n){
        int a[n+1],cnt=0;
        memset(a,0,sizeof(a));
        for(int i=m;i<=n;i++){
            if(!a[i]){  // a[i]是素数
                ++cnt;
                for(int j=i*2;j<=n;j+=i)
                    a[j]=1;
            }
        }
        cout<<cnt<<endl;
    }
}


发表于 2020-06-13 19:05:40 回复(0)
最开始我的思路是求出素数 再添加进素数组 下次判断的时候判断能否判断被所有素数整除 ,后来我又想一个数整除一个数 那被除的数要小于除数的一半才行但是速度还是不够快  再后来我就随着位数不断加大除数的大小 ..虽然很莫名其妙但是速度却还挺快 百万位只花了1秒左右 有大佬能看懂的话希望能告诉我一下这是为什么..
using System;
using System.Collections.Generic;

//输入M、N,1 < M < N < 1000000,求区间[M,N]内的所有素数的个数。素数定义:除了1以外,只能被1和自己整除的自然数称为素数
namespace HalloWrold
{
    class ClassMain
    {
       static int lastLength = 0;
        static int b = 2;
   
        static void Main(string[] args)
        {
            //System.Console.ForegroundColor = System.ConsoleColor.Yellow;

            int n, m;
            string num = Console.ReadLine();
            n = Convert.ToInt32(num.Substring(0, num.IndexOf(" ")));
            m = Convert.ToInt32(num.Substring(num.LastIndexOf(" ")));
            int count = 0;
            

            List<int> arr = new List<int>();        //素数数组
            arr.Add(2);

            for (int i = 2; i <= m; i++)
            {
                int t = jd(arr.Count);
                for (int j = 0; j < t; j++)
                {
                    if (i % arr[j] == 0)
                        break;
                    if (j ==t- 1)
                    {
                        count++;
                        arr.Add(i);
                     
                    }
                }

            }
            if (m > 1)
                count++;
            Console.WriteLine(count);
        }

        public static int jd(int count)
        { 
            if (lastLength!= count.ToString().Length+1)             //说明位数变化
            {
                b *= 2;
                lastLength = count.ToString().Length + 1;      
            }
            
            if (count  <1000)
                return count;
            else
            {              
                return count / b;
            }
              
        }
    }

}

发表于 2020-04-01 16:50:57 回复(0)
#include<stdio.h>
#include<math.h>
int main()
{
    int m=0,n=0;
    int j=0;
    int count=0;
    scanf("%d %d",&m,&n);
    for(int i=m;i<=n;i++)
    {
        for(j=2;j<=sqrt(i);j++)
        {
            if(i%j==0)
                break;
        }
        if(j>sqrt(i))
            count++;
    }
    printf("%d",count);
    return 0;
}
发表于 2020-02-18 14:53:02 回复(0)
这里给出一种 O(n) 做法,且常数很小。
利用线性筛法可以很容易地求出1~n的素数个数。
而现在要求的是m~n的素数个数,所以我们考虑如何求1~m-1的素数个数。
事实上在线性筛过程中,筛到数m-1后素数的个数即为1~m-1的素数个数。将它与1~n的素数个数相减即是答案。
#include<cstdio>
int m,n,cnt2,cnt,v[1000010],p[200010];
int main() {
    scanf("%d%d",&m,&n);
    for (int i=2; i<=n; ++i) { //线性筛
        if (i==m) cnt2=cnt; //记录[1,m)区间内的素数个数
        if (!v[i]) v[i]=p[++cnt]=i;
        for (int j=1; j<=cnt; ++j) {
            int t=p[j];
            if (1ll*t*i>n||t>v[i]) break;
            v[t*i]=t;
        }
    }
    printf("%d\n",cnt-cnt2);
    return 0;
}


发表于 2019-08-15 18:22:53 回复(0)
//埃氏筛法 复杂度 O(√nlogn)
 for (int i = 2; i*i <= num; ++i) {
        if (!mark[i]) {
            for (int j = i * i; j <= num; j += i) {
                mark[j] = 1;
            }
        }
    }
发表于 2019-06-22 16:08:53 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int M=sc.nextInt();
        int N=sc.nextInt();
        boolean[] isPrime=new boolean[N+1];
        //注意2为素数
        isPrime[2]=true;
        for(int i=3;i<N+1;i++){
            if((i&1)==1){
                //先让奇数为true
                isPrime[i]=true;
            }
        }
        for(int i=3;i<=Math.sqrt(N);i+=2){
            if(isPrime[i]){
                for(int j=i+i;j<=N;j+=i){
                    isPrime[j]=false;
                }
            }
            
        }
        int count=0;
        for(int i=M;i<=N;i++){
            if(isPrime[i]){
                count++;
            }
        }
        System.out.println(count);
    }
}

发表于 2019-06-14 19:41:18 回复(0)
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;

const int M=1000000;

int l,r;
bool prime[M+1];    //标记下标是否为素数 

void input(){
    cin>>l>>r;
}

//求素数表 
void findPrime(){
    for(int i=2;i<=M;i++){
        prime[i]= true;
    }
    for(int i=2;i*i<=M;i++){
        if(prime[i]){
            for(int j=2*i;j<=M;j++){
                if(j%i==0){
                    prime[j]= false;
                }
            }
        }
    }
}



void handle(){
    int ans = 0;
    for(int i = l;i<=r;i++){
        if(prime[i]){
            ans++;
        }
    }
    cout<<ans<<endl;
}



int main(){
    input();
    findPrime();
    handle();
    return 0;
}
发表于 2019-04-08 22:29:41 回复(0)
素数的倍数一定不是素数。
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
int getParm(int m,int n);
int main(){     int m,n;     cin >> m >> n;     cout << getParm(m,n) << endl;
} 
int getParm(int m,int n){     //求m,n之间有多少个素数     //统计2到m之间的所有素数     vector<int> param;     int count = 0;     param.push_back(2);     count++;     for(int i = 3; i < m;i++){         vector<int>::iterator it;         for(it = param.begin(); *it < sqrt(i); it++){             if( i % (*it) == 0){                 break;             }         }         if(*it > sqrt(i)){             param.push_back(i);         }     }     for(int i =  m > 3 ? m : 3; i <= n;i++){         vector<int>::iterator it;         for(it = param.begin(); *it <= sqrt(i);it++){             if( i % (*it) == 0){                 break;             }         }         if(*it > sqrt(i)){             param.push_back(i);             count++;         }     }     return count; 
} 

发表于 2019-04-07 23:36:01 回复(0)
#include<stdio.h>
#include<math.h>
int main()
{
    int i,j,c,num,M,N;
    while(scanf("%d%d",&M,&N)!=EOF)
    {
        num=0;
        for(i=M;i<=N;i++)
        {
            c=sqrt(i);
            for(j=2;j<c+1;j++)
                if(i%j==0) break;
        if(j>c)num++;
        }
        printf("%d\n",num);
    }
    return 0;
}
发表于 2019-04-01 21:58:20 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 埃拉托斯特尼筛法 O(n*log(log(n)))
 * @author wylu
 */
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] strs = br.readLine().split(" ");

        int m = Integer.parseInt(strs[0]), n = Integer.parseInt(strs[1]);
        System.out.println(simpleSieve(m, n));
    }

    private static int simpleSieve(int m, int n) {
        //元素值为false表示该元素下标值为素数
        boolean[] mark = new boolean[n + 1];
        
        for (int i = 2; i <= n; i++) {
            if (!mark[i]) {
                for (int j = 2 * i; j <= n; j += i) {
                    mark[j] = true;
                }
            }
        }
        int count = 0;
        for (int i = m; i <= n; i++) {
            if (!mark[i]) count++;
        }
        return count;
    }
}

发表于 2019-01-22 11:27:36 回复(0)