利用数组求前n个质数

我的算法思想和实现方式都在代码和注释当中呢,这样的方式确实使算法复杂度降低一个等级,很好啊。

#include <stdio.h>
#include <time.h>

/**
 * 利用数组求前n个质数
 * 确定一个数m是否为质数,可以用已求出的质数对m
 * 的整除性来确定
 */

//如果不知道质数的特性和想不到优化思路的方法
void getNPrimes_normal();

//优化之后的方法
void getNPrimes_optimize();

int main(void)
{
    clock_t start,end;

    start = clock(); //开始时,取得开始时间。

    //通常的做法的运行时间,输入的n=10000
    //getNPrimes_normal();

    //优化后的运行时间
    getNPrimes_optimize();

    end = clock();   //结束时,取得结束时间

    printf("Run time: %lf S",(double)(end-start)/CLOCKS_PER_SEC);

    return 0;
}

//通常用到的想法
void getNPrimes_normal(){
    /**
     * 用于保存质数的数量
     * @brief count
     */
    int count;
    printf("Please the count of prime number:\n");

    scanf("%d",&count);

    //使用数组来保存所求出的质数
    int primes[count];

    /**
     * 首先,第一个已知的质数是2,
     * 则计算应该从3开始
     */
    primes[0] = 2;
    int pc = 1;

    int m = 3; //从数字3开始

    while(pc < count){

        int k = 0;

        // 这里只要找不到质数,就会一直在这个循环中
        while(k < pc){
            if(m % primes[k] == 0){
                m += 1;
                k = 0;
            }else{
                k++;
            }
        }

        //找到质数之后,跳出上面的循环
        //这个的执行是先执行primes[pc] = m;
        //再去执行pc++;
        primes[pc++] = m;
        m+=1;
    }

    /**
     * 对质数进行输出操作
     *
     */
    for(pc = 0;pc < count;pc++){
        printf("%4d\t",primes[pc]);
    }

}

//优化之后的方法
void getNPrimes_optimize(){
    /**
     * 用于保存质数的数量
     * @brief count
     */
    int count;
    printf("Please the count of prime number:\n");

    scanf("%d",&count);

    //使用数组来保存所求出的质数
    int primes[count];

    /**
     * 首先,第一个已知的质数是2,
     * 则计算应该从3开始
     */
    primes[0] = 2;
    int pc = 1;

    int m =3; //从数字3开始

    while(pc < count){

        /**
         * 首先需要解决的是如何判断一个数是一个质数
         * 1:除了数字2之外,其他所有的质数都是奇数
         * 2:假设某一个数字是k,只要判断k能否被k之前
         *    的质数整除就可以了,如果能够整除,则k就是
         *    合数,如果不能整除,k就是质数
         *
         *    但是,为了减少算法的复杂度,我们这样设想
         *    p*q=k
         *    则肯定p和q中:
         *    p*p <=k的话,q*q >= k
         *    则,只要求k能否被k的平方根之前的数字整除就可以了。
         *
         *    基于这个思想,我们的实现方式如下:
         */

        int k = 0;

        // 这里只要找不到质数,就会一直在这个循环中
        while(primes[k] * primes[k] <= m){
            if(m % primes[k] == 0){
                m += 2; //除了数字2之外,其他所有的质数都是奇数
                k = 1; //不用使用数字2去测试
            }else{
                k++;
            }
        }

        //找到质数之后,跳出上面的循环
        //这个的执行是先执行primes[pc] = m;
        //再去执行pc++;
        primes[pc++] = m;
        m+=2;
    }

    /**
     * 对质数进行输出操作
     *
     */
    for(pc = 0;pc < count;pc++){
        printf("%4d\t",primes[pc]);
    }
}

下面是我的运行结果,第一个是没有优化的结果,第二个是经过算法优化后的结果,效果还是很明显的。

这个是没有优化的结果:

这个是优化之后的结果:

时间: 2024-10-06 03:40:53

利用数组求前n个质数的相关文章

算法题:求前n个质数的和

#include <iostream> using namespace std; //编一个程序求质数的和例如F(7) = 2 + 3 + 5 + 7 + 11 + 13 + 17 = 58. int Grial(int n) { int *b = new int[n]; int k = 0; b[k++] = 2; int i = 2; int j; int count = b[0]; while (i++) { if (k == n)break; for (j = 0; j*j <

算法导论学习之线性时间求第k小元素+堆思想求前k大元素

对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思路例如以下: 1.分解:将A[p,r]分解成A[p,q-1]和A[q+1,r]两部分.使得A[p,q-1]都小于A[q],A[q+1,r]都不小于A[q]; 2.求解:假设A[q]恰好是第k小元素直接返回,假设第k小元素落在前半区间就到A[p,q-1]递归查找.否则到A[q+1,r]中递归查找. 3

树状数组求区间最值

树状数组求区间最值 树状数组(Binary Index Tree)利用二进制的一些性质巧妙的划分区间,是一种编程,时间和空间上都十分理想的求区间和的算法,同样我们可以利用树状数组优美的区间划分方法来求一个序列的最值 约定以 num[]  表示原数组, 以 idx[] 表示索引数组, Lowbit(x)=x&(-x) 树状数组求和时通过构造数组 idx[] 使 idx[k]=sum(num[tk]), tk [k-Lowbit(k)+1,k], 使用同样的方法构造最值索引数组: 以最大值为例, 先

[nowCoder] 两个不等长数组求第K大数

给定两个有序数组arr1和arr2,在给定一个整数k,返回两个数组的所有数中第K小的数.例如:arr1 = {1,2,3,4,5};arr2 = {3,4,5};K = 1;因为1为所有数中最小的,所以返回1: arr1 = {1,2,3};arr2 = {3,4,5,6};K = 4;因为3为所有数中第4小的数,所以返回3: 要求:如果arr1的长度为N,arr2的长度为M,时间复杂度请达到O(log(min{M,N})). 这题目的难度在于时间复杂度请达到O(log(min{M,N})),参

一维数组求最大子数组(解决溢出问题)

一.题目要求 题目:返回一个整数数组中最大子数组的和. 要求: 要求程序必须能处理1000 个元素: 每个元素是int32 类型的: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 二.设计思想 程序在宏里面定义出了数组长度的大小,在长度超过100万的时候程序直接崩溃,其实这并不是因为结果太大导致的数值溢出,而是因为内存溢出,我们的数组是定义在程序内部的,属于局部变量,存放位置在栈上

Hadoop阅读笔记(二)——利用MapReduce求平均数和去重

前言:圣诞节来了,我怎么能虚度光阴呢?!依稀记得,那一年,大家互赠贺卡,短短几行字,字字融化在心里:那一年,大家在水果市场,寻找那些最能代表自己心意的苹果香蕉梨,摸着冰冷的水果外皮,内心早已滚烫.这一年……我在博客园-_-#,希望用dt的代码燃烧脑细胞,温暖小心窝. 上篇<Hadoop阅读笔记(一)——强大的MapReduce>主要介绍了MapReduce的在大数据集上处理的优势以及运行机制,通过专利数据编写Demo加深了对于MapReduce中输入输出数据结构的细节理解.有了理论上的指导,仍

利用矩阵求斐波那契数列

利用矩阵求斐波那契数列 flyfish 2015-8-27 矩阵(matrix)定义 一个m*n的矩阵是一个由m行n列元素排成的矩形阵列.矩阵里的元素可以是数字符号或者数学式. 形如 {acbd} 的数表称为二阶矩阵,它由二行二列组成,其中a,b,c,d称为这个矩阵的元素. 形如 {x1x2} 的有序对称为列向量Column vector 设 A={acbd} X={x1x2} 则 Y={ax1+bx2cx1+dx2} 称为二阶矩阵A与平面向量X的乘积,记为AX=Y 斐波那契(Fibonacci

数状数组求逆序对

逆序对在很多地方用的到.以前都是用归并排序或线段树求,在<mato的文件管理>看到有人用树状数组求,很简单!整理如下: 思路: 首先,开一个大小为这些数的最大值的数组,作为树状数组. 然后,将各个数按顺序依次加入该数组.方法为:这个数大小对应的它在线段树中的位置,对这个位置上的数加1,并更新树状数组.所以当前树状数组中存着所有原数字序列中当前数前面的数,而getsum(i)就是 i 前面小于等于 i 的数的个数.i-getsum(i)-1也就是大于它的个数.这就是逆序对了. 把每一个的逆序对数

循环一维数组求最大子数组

题目: 随机出一个一维数组,设该数组为循环数组,求其最大小子数组. 一.设计思路 求最大子数组,就求出最大的连续正子数组. 将数组分为全负和有非负值两种情况.全负求出最大值即可. 在有非负值的情况下,先判断该随机数组的首尾是否相连,即首尾是否都大于等于零.如果首尾相连,则将该一维数组分为首.中.尾三部分,先求出首尾和S1,再求中间最大连续正子数组和S,令S1和S与maxS相比较,求出最大子数组:如果首尾不相连,则直接借鉴前一种情况中部的算法,求最大正子数组S. 二.源代码 1 //刘双渤,刘洪阳