你能告诉我为什么这会在spoj中产生时间限制(Prime数字生成器)

时间:2010-01-15 07:31:09

标签: c++ generator primes

#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;    

bool prime[1000000500];
void generate(long long end)
{
    memset(prime,true,sizeof(prime));
    prime[0]=false;
    prime[1]=false;

        for(long long i=0;i<=sqrt(end);i++)
        {
         if(prime[i]==true)
         {
             for(long long y=i*i;y<=end;y+=i)
             {
                 prime[y]=false;
             }
         }
        }
}

int main()
{
    int n;
    long long b,e;
    scanf("%d",&n);
    while(n--)
    {
        cin>>b>>e;
        generate(e);
        for(int i=b;i<e;i++)
        {
            if(prime[i])
                printf("%d\n",i);
        }
    }
    return 0;
}

这是我的spoj prime generator代码 Altought它生成与另一个接受的代码相同的输出。

7 个答案:

答案 0 :(得分:2)

您不需要筛选每个数字到最终数字。那太傻了。仅在开始和结束编号之间的范围内操作。 (部分筛)

我在Python中解决了这个问题,这就是我最终设法做到的方式。我也开始计算所有素数直到潜在最大值的平方根,1000000000。这只是31623所以它不需要很长时间。

从此列表中使用最大为当前案例最大值的平方根的那些数字来筛选当前案例。

答案 1 :(得分:2)

此问题需要Segmented Sieve实现。 Eratosthenes的简单分段筛可以在大约50-60行代码中用C / C ++轻松编程。 如果实现分段筛,则只需为问题中提到的最大大小的段分配内存。

还有一些其他优化可以帮助一点。我将列出我在解决方案中所做的那些:

  • 检查素数的倍数,直至最大数的平方根。

  • 可以预先计算所有素数的查找数组,直到最大可能数的平方根,即sqrt(10 ^ 9),并将其添加到源代码中。此问题的SPOJ源代码大小限制为50000字节,添加此查找数组仍然符合此大小限制。

  • 在越过倍数时,从y = i * i开始,但只检查i的奇数倍。

通过这些优化,我在C ++中的代码运行大约0.05秒。即使没有这些 优化我认为分段筛应该被接受。希望这会有所帮助。

答案 2 :(得分:1)

让它更快的一个简单方法是从for循环中取出sqrt

double sqrtOfEnd = sqrt(end);
for(long long i=0; i<=sqrtOfEnd; i++)
{
  ...

您不需要在每个循环上重新计算平方根 正如其他人所指出的那样,这可能还不够,你可能必须采用其他方法来寻找素数。

答案 3 :(得分:1)

由于您需要从多个序列中输出素数,可能会保留以前筛选的结果,并且只会根据需要继续填写表格的其余部分吗?

答案 4 :(得分:0)

你需要加快速度 - 对于测试案例,如999900000-1000000000,Eratosthene的筛选算法太慢了。您可以尝试其他替代方案,并将产生更好的结果。

PS。我当然不会告诉你这些是什么。做你的作业。 :P

答案 5 :(得分:0)

@nakedfantaic 恰好!

#include <cstdio>
#include <cmath>

unsigned int numbers[3500], len;

inline bool prime(unsigned int x)
{
    unsigned int i, last = sqrt(x);
    for (i = 2; i <= last; i++) {
        if (!(x % i)) {
            return 0;
        }
    }
    return 1;
}

void generate()
{
    for (unsigned int i = 2; i < 32000; i++) {
        if (prime(i)) {
            numbers[len++] = i;
        }
    }
}

inline bool process(unsigned long x)
{
    unsigned int i, last = sqrt(x);
    for (i = 0; i < len && numbers[i] <= last; i++) {
        if (!(x % numbers[i])) {
            return 0;
        }
    }
    return 1;
}

int main()
{
    int tests;
    unsigned long begin, end;
    generate();
    scanf("%d", &tests);
    while (tests-- > 0) {
        scanf("%u %u", &begin, &end);
        if (begin == 1) {
            begin++;
        }
        while (begin <= end) {
            if (process(begin)) {
                printf("%u\n", begin);
            }
            begin++;
        }
        printf("\n");
    }
    return 0;
}

http://pastebin.com/G5ZRd5vH

答案 6 :(得分:0)

我可以帮助python 3.4和我的工作代码为spoj(素数生成器)是这样的:

import math
primes = [True for i in range(int(math.sqrt(1000000000))+1)]
tes = int(math.sqrt(math.sqrt(1000000000)*2))+1
for i in range(2,tes):
    if primes[i]:
        for z in range(i*i,int(math.sqrt(1000000000))+1,i):
            primes[z] = False
for z in range(int(input().strip())):
    m,n = map(int,input().strip().split())
    if n == 1:
        print('')
        continue
    elif m == 1:
        m += 1
    ans = [True for i in range(n-m+1)]
    for i in range(2,int(math.sqrt(1000000000))+1):
        if primes[i]:
            if i > n:
                break
            num = m//i
            if num*i != m:
                num += 1
            if num < 2:
                num = 2
            while num*i <= n:
                ans[num*i-m] = False
                num += 1
    for i in range(n-m+1):
        if ans[i]:
            print(i+m)
    print('')
相关问题