zoukankan      html  css  js  c++  java
  • 论如何对暴力素数算法进行简单优化

    简介

    PAT1013

    这是之前发的一道简单的PAT题目–数素数(PAT1013),由于这道题官方要求的素数范围极小,所以暴力遍历即可解决。

    素数暴力求法(未优化)

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int prime[10005];
    
    bool isPrime(int i)
    {
        for(int j = 2; j <= (int)sqrt(i); j++)
        {
            if(i % j == 0)
            {
                return false;
            }
        }
        return true;
    }
    
    int main(void)
    {
        int num = 0;
        int i = 0;
        int begin = 0, end = 0;
        int count = 1;
        memset(prime, 0, sizeof(prime));
        scanf("%d %d", &begin, &end);
        for(i = 2;; i++)
        {
            if(num == end)
            {
                break;
            }
            if(isPrime(i))
            {
                prime[num++] = i;
            }
        }
        for(i = begin - 1; i <= end - 1; i++)
        {
            if(count % 10 != 0)
            {
                if(i == end - 1)
                {
                    printf("%d", prime[i]);
                    break;
                }
                printf("%d ", prime[i]);
                count++;
            }
            else
            {
                printf("%d
    ", prime[i]);
                count++;
            }
        }
        return 0;
    }

    经过优化后,我们在3之后只求奇数,让目标奇数只与之前求过的素数取余,且把遍历素数范围控制在sqrt(已求素数总数)范围内。

    优化后的暴力代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int prime[10005];
    
    int main(void)
    {
        int num = 2;
        int i = 0, j = 0;
        int begin = 0, end = 0;
        int count = 1;
        memset(prime, 0, sizeof(prime));
        scanf("%d %d", &begin, &end);
        prime[0] = 2;
        prime[1] = 3;
        for(i = 5; ; i += 2) //只求奇数
        {
            if(num >= end)
            {
                break;
            }
            for(j = 0; j <= (int)sqrt(num); j++) //缩减循环次数
            {
                if(i % prime[j] == 0) //与之前已经求过的prime数组中的数取余
                {
                    break;
                }
                else
                {
                    if (j + 1 > (int)sqrt(num))
                    {
                        prime[num++] = i;
                        break;
                    }
                }
            }
        }
        for(i = begin - 1; i <= end - 1; i++)
        {
            if(count % 10 != 0)
            {
                if(i == end - 1)
                {
                    printf("%d", prime[i]);
                    break;
                }
                printf("%d ", prime[i]);
                count++;
            }
            else
            {
                printf("%d
    ", prime[i]);
                count++;
            }
        }
        return 0;
    }

    优化后的算法遍历大规模素数的时间是原算法的一半。

    测试

    • 优化前
      优化前

    • 优化后
      优化后

  • 相关阅读:
    Golang:命令行框架cobra简介
    kafka集群管理工具kafkamanager
    GAN 简介
    部分梯度下降算法简述
    EfficientNet 简介
    数据库查表空间Oracel、Vertica
    Vue 组件自动注册
    使用jmeter+操作BeanShell调用java生成jar包实例
    ACCESS数据库中SQL语句,数字不必加'123'
    反射取得静态类中的属性,方法,字段
  • 原文地址:https://www.cnblogs.com/csnd/p/12897021.html
Copyright © 2011-2022 走看看