【问题标题】:optimize this code so that it code run in less than 1s优化此代码,使其代码在不到 1 秒的时间内运行
【发布时间】:2014-07-17 05:47:22
【问题描述】:

我已经编写了这个 c 程序。这运作良好。我想要非常大的值,比如 1000000。这应该在不到 1 秒的时间内运行。

这个程序为 n>1 生成一个序列。 a[0]=a[1]=0 和 a[n]=a[n-1]+f(n),其中 f(n) 是 n 的最小质因数。

#include<stdio.h>
int fn(long no)
{
    long i;
    for (i = 2; i <= no; i++)
    {
        if (no % i==0)
        {
            return i;
            break;
        }
    }
}

int main(void)
{
    int t,i;
    long n,a1,j;
    scanf("%d",&t);

    for(i=0;i<t;i++)
    {
        a1=0;
        scanf("%ld",&n);
        for(j=2;j<=n;j++)
        {
            a1 = a1 + fn(j);

        }
     printf("%d\n",a1);
    }
}

【问题讨论】:

  • 为什么它应该在不到 1 秒的时间内运行?现在需要多长时间,因为在另一台机器上会有所不同?
  • n=100000 耗时超过 2s。
  • 您是否启用了编译器优化?
  • 其实这是一个关于spoj的问题,显示的时间限制已经超出。
  • 你一开始就应该说这是一个 SPOJ 问题,你应该给出 URL。此外,有许多网页为此类问题提供解决方案。老实说,你真的用谷歌搜索过吗?

标签: c performance optimization


【解决方案1】:

只要修改如下,你就会看到很大的不同:

#include<math.h>

int fn(long no)
{
    long i;
    int sqrtno= (int)sqrt((double)no);
    for (i = 2; i <= sqrtno; i++)
    {
        if (no % i==0)
        {
            return i;
        }
    }

    return no;
}

当你达到no的平方根时,不需要继续搜索除数,因为当一个除数比这个大时,另一个比这个小。

【讨论】:

  • 我试过了,但这并没有给我所需的答案。
  • 看我的回答,在默认情况下你有一个未定义返回的函数(循环结束而没有找到任何答案)
  • 完全正确。当no 是素数时,这会有所不同。我正在发布更新的代码,现在检查。我很惊讶编译器没有警告我......
  • 谢谢它有效,但它不能为 10000000 工作。花费大量时间。
  • 不要将它用于这么高的值,您需要更有效的方法。您可以在这项研究上投入多少精力?
【解决方案2】:

这个程序在 [2, n] 范围内求最小素因数之和。

您可以设置一个包含 n 个元素的 int 数组,将其初始化为 0。然后,使用埃拉托色尼筛法算法来标记每个素数的倍数。当一个数 i 是素数 x 的倍数时,检查它是否被标记为 off,如果没有,则将 x 存储到 element[i] 中。

然后,对数组中的所有数字求和。

【讨论】:

  • 是的,我会注意的。谢谢。
【解决方案3】:

如果它几乎足够快但不够快,请记住质数只能是以 1、3、7、9 结尾的数字。所以 j 可以在 2 中上升,如果 fn 以 5 结束,则不会下降。这应该会给你 60% 的提升。

【讨论】:

  • 49 不是素数,21 不是素数,63 不是素数 :(
【解决方案4】:

问题是循环:

for (i = 2; i <= no; i++)

应该是

for (i = 2; i * i <= no; i++)

然后你在return之后去掉break,并添加:

return no;

在函数结束时,循环完成后。

解释: 您不需要检查 2 和 n 之间的所有可能因素。如果在 2 和 sqrt(n) 之间找不到任何因子,则 n 是质数,它就是您要查找的数字。

【讨论】:

  • 谢谢你,它有效,但它不适用于 10000000。花费大量时间。
  • 并且使用 sqrt() 更快。
猜你喜欢
  • 2015-11-15
  • 2017-10-18
  • 1970-01-01
  • 2013-01-30
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多