论如何对暴力素数算法进行简单优化

简介

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;
}

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

测试

  • 优化前
    优化前

  • 优化后
    优化后

原文地址:https://www.cnblogs.com/csnd/p/12897021.html