当前位置: 首页 > 知识库问答 >
问题:

这是埃拉托斯特尼筛的什么变体?

终翰学
2023-03-14

我正在尝试解决spoj上的Prime Path问题,我正在尝试理解在github上找到的解决方案。解决这个问题的广义逻辑是生成所有四位数素数,并添加一个边,如果我们可以通过更改一个数字从一个素数转到下一个素值。我找到的这个解决方案使用筛子来生成所有素数。与此解决方案中的筛分功能相比,维基上的稀土筛分功能有所不同。只需要帮助了解以下代码中筛分函数的变化:

#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>
using namespace std;

#define MAX 10000
#define LMT 100

bool flag[MAX], visited[MAX];
int d[MAX];

void sieve()
{
    register int i, j, k;
    flag[0] = flag[1] = 1;
    for(i=1000; i<MAX; i+=2) 
        flag[i] = 1;
    for(i=3; i<LMT; i+=2)
        if(!flag[i])
            for(j=i*i, k=i<<1; j<MAX; j+=k)
                flag[j] = 1;
}

int bfs(int start, int end)
{
    queue< int > Q;
    int i, u, v, t, j;
    char temp[10], x;
    Q.push(start);
    memset(visited, 0, sizeof visited);
    memset(d, -1, sizeof d);
    d[start] = 0;
    visited[start] = 1;
    while(!Q.empty())
    {
        u = Q.front();
        Q.pop();
        sprintf(temp,"%d",u);
        x = temp[0];
        for(t=0;t<4;t++)
        {
            if(t==0 || t==3) 
                i=1; 
            else
                i=0;
            if(t==3) 
                j=2;
            else
                j=1;
            x = temp[t];
            for(;i<=9;i+=j)
            {
                temp[t] = i+'0';
                v = atoi(temp);
                if(v!=u && !visited[v] && !flag[v])
                {
                    Q.push(v);
                    visited[v] = 1;
                    d[v] = d[u]+1;
                    if(v==end) 
                        return d[end];
                }
            }
            temp[t] = x;
        }
    }
    return d[end];
}

int main()
{
    int a, b, t, dist;
    sieve();
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %d", &a, &b);
        if(a==b) 
        {
            printf("0\n"); 
            continue; 
        }
        dist = bfs(a,b);
        if(dist==-1) 
            printf("impossible\n");
        else 
            printf("%d\n", dist);
    }
    return 0;
}

这里的筛选函数计算是什么?我无法理解为什么作者只列出奇数来计算素数,为什么循环达到LMT,即100?感谢你的帮助。

共有1个答案

狄凯
2023-03-14

我不明白为什么作者只列出了奇数来计算质数

因为唯一的偶素数是2,其余的都是奇数。所以你只需要检查奇数。

为什么循环运行到LMT,即100?

因为< code>100 * 100 = 10000,所以您可以通过筛选到100来筛选所有4位素数。通过标出数字的倍数<代码>

for(j=i*i, k=i<<1; j<MAX; j+=k)
    flag[j] = 1;

注意i

此外,我们从i*i开始,因为之前的数字将被i的先前迭代筛选,原因相同:如果j

如果需要,您可以进一步优化代码,作为练习:

>

  • 你只筛选奇数,但你仍然为偶数分配内存。用一半的内存实现筛子;

    每个数字只需要 1 位。实现内存减少 16 倍的筛网(对于每个数字不使用 bool,减少 8 倍,对于不为偶数分配内存,则少 2 倍)。

  •  类似资料:
    • 我正在尝试编写一个程序来实现对埃拉托西的筛选。我可以从2到任何给定的结束编号,但我们正在处理的赋值要求我们输入起始值。我完全被卡住了。我试过很多不同的代码,但它总是给我奇怪的答案。 我的起点是起始值,终点是结束值。我基本上想找到这个范围的素数。谢谢!!!

    • 做一个简单的筛子很容易: 但是当N非常大并且我无法在内存中持有这种数组时,该怎么办?我已经查找了分段筛方法,它们似乎涉及查找素数,直到sqrt(N),但我不明白它是如何工作的。如果 N 非常大(比如 10^18)怎么办?

    • 在一个类作业中,我被要求用Java编写Eratostenes筛选代码,我的代码效率非常低。运行时间不长,但我相当肯定,除了像我一样列出所有内容外,还有其他循环的空间。。 这是我的代码: 基本上,我所做的是将所有不是质数的元素设置为true… 所以我的主要2个问题是1。有没有办法实现一个循环,使代码更短2。如何打印此数组中所有为 true(质数)的元素

    • 我在我的一个班级里做的一个作业,我们必须实现一个厄拉多塞的筛子。我已经尝试了七次来得到一个有效的代码,并且尝试了整合我研究过的许多解决方案。我终于有一个可以输出数字的了。不幸的是,它同时打印合数和质数,但不打印2。 我的代码如下: 我怀疑我的循环有问题。我修复了前两个循环的和变量,以便它从2开始打印出来,问题似乎是在我将数组初始化为true后,它没有将合数标记为。 提前感谢你的帮助。

    • 我的任务如下:使用埃拉托斯特尼筛来定位并打印出从1到1000的所有素数。 遵循与此类似的过程: < li >按顺序写下所有需要考虑的数字。 < li >划掉1,因为它不是质数。 < li >转到未删除的下一个号码;留下它,但是划掉那个数字的所有倍数。 < li >重复步骤3,直到您超过所考虑的最大值的一半。在这一点上,所有没有被划掉的数字都是期望的素数。 您的算法可能与上述算法略有不同,但速度很重

    • 我正在实现一个相当快的质数生成器,我得到了一些不错的结果,在埃拉托斯特尼的筛子上进行了一些优化。特别是,在算法的初步部分,我以这种方式跳过2和3的所有倍数: 这里是一个根据埃拉托色尼筛的布尔数组。我认为这是一种只考虑质数2和3的轮式因式分解,按照模式2、4、2、4递增。. 我想做的是实现一个更大的轮子,也许考虑素数2,3和5。 我已经阅读了很多关于它的文档,但我没有看到任何使用埃拉托斯特尼筛子的实