如何使此代码适用于大输入值?

时间:2014-06-19 12:05:56

标签: c

#include <stdio.h>

int main()
{
    int i,j,k,t;
    long int n;
    int count;
    int a,b;
    float c;

    scanf("%d",&t);
    for(k=0;k<t;k++)
    {
        count=0;
        scanf("%d",&n);
        for(i=1;i<n;i++)
        {

            a=pow(i,2);
            for(j=i;j<n;j++)
            {
                b=pow(j,2);
                c=sqrt(a+b);
                if((c-floor(c)==0)&&c<=n)
                ++count;


            }


        }
        printf("%d\n",count);
    }
    return 0;
}

以上是一个c代码,用于计算范围1..n范围内毕达哥拉斯三元组的数量。 我该如何优化它?它耗费大量输入。 1·; = T&LT; = 100 1·; = N&LT = 10 ^ 6

3 个答案:

答案 0 :(得分:1)

你的内部两个循环是O(n * n)所以没有太多可以在不改变算法的情况下完成。只是看看内循环,我能在短时间内得出的最好结果如下:

unsigned long long int i,j,k,t;
unsigned long long int n = 30000;  //Example for testing
unsigned long long int count = 0;
unsigned long long int a, b;
unsigned long long int c;
unsigned long long int n2 = n * n;

for(i=1; i<n; i++)
{
    a = i*i;

    for(j=i; j<n; j++)
    {
        b = j*j;

        unsigned long long int sum = a + b;
        if (sum > n2) break;

              // Check for multiples of 2, 3, and 5
        if ( (sum & 2) || ((sum & 7) == 5) || ((sum & 11) == 8) ) continue;

        c = sqrt((double)sum);
        if (c*c == sum) ++count;
    }
}

一些评论:

  • 对于n = 30000的情况,这大约是原始速度的两倍。
  • 如果您不介意将其限制在65535,则可以切换到unsigned int以获得x2速度增加(或比原始速度快约x4)。
  • 检查2/3/5的倍数会使速度提高一倍。您可以通过查看this question的答案来增加这一点。
  • i > 65535时原始代码有整数溢出,这就是我为所有内容切换到64位整数的原因。
  • 我认为由于浮点数固有的精度,你检查完美正方形的方法并不总是有效。我的示例中的方法应该绕过它,并且反正稍微快一些。
  • 您仍然必须使用O(n * n)算法。在我的机器上,n = 30000的代码在大约6秒内运行,这意味着n = 1000000的情况将花费近2个小时。查看Wikipedia会显示您可以探索的许多其他算法。

答案 1 :(得分:0)

这实际上取决于您期望的基准。

但就目前而言,力量功能可能是瓶颈。我想你可以做以下两件事之一:

a)预先计算并保存在文件中,然后将所有平方值加载到字典中。根据输入大小,可能会加载内存。

b)记住先前计算的平方值,以便再次询问时,可以通过节省CPU时间在那里重复使用它。这再一次,最终会加载你的记忆。

答案 2 :(得分:0)

您可以将索引定义为(unsigned)long或甚至(unsigned)long long,但是您可能必须使用big num库来解决大量问题。使用未签名的uppers您的Max数​​量限制但强制您使用正数。我怀疑你是否需要更长的时间。 您的问题似乎是优化代码以使其更快。如果您阅读毕达哥拉斯三元组,您将看到有一种方法可以使用整数参数计算它们。如果3 4 5是三元组,那么我们知道2 * 3 2 * 4 2 * 5也是三元组,k * 3 k * 4 k * 5也是三元组。您的算法正在检查所有这些三元组。有更好的算法可供使用,但我担心你必须在Google上搜索关于毕达哥拉斯三胞胎的研究。