【问题标题】:How to make the computation faster?如何让计算更快?
【发布时间】:2020-07-24 06:03:41
【问题描述】:

这是一个简短的代码,它计算所有平方数的总和(实际上不是平方和),直到 n,其中 n 可以达到 10 pow 20。

    long long res=0;
    long long sm=0;

    for (long long i = 1; res <=n; i=i+2)
    {
        res = (res+i);
        sm  = sm+(res*(n/res));

    }

我们如何让上面的代码运行得更快?在这里,对于非常大的 n,例如 10 pow 20,sm 的计算需要时间。

有什么方法可以加快sm的计算速度?

这里 res 计算所有平方数,例如 1,4,9,16,25....

假设 n=10,那么正方形是 1,4,9,然后根据上面的代码,sm 是 (1)(10/4)+(4)(10/4)+(9)(10 /9)=27。

1*10+4*2+9*1=27。

这里的除法是整数除法。

编辑1:

我需要计算上面代码中提到的sm

这里sm 是求和(i2 * floor(n/(i2))),其中 i=1 到 sqrt (n)

【问题讨论】:

  • 如果您正在尝试回答一些在线判断测试或代码测验,请添加原始问题陈述的链接。一方面,我肯定不明白你应该做什么。
  • codeforces.com/contest/616/problem/E ,spoj.com/problems/SUMPRO 是两个类似的问题。我只是想知道如何解决上述问题,只是出于好奇,我正在我的系统上运行。但它非常慢。
  • 请张贴原始问题的链接。你的问题描述不清楚。 SQRT 结果是两倍。你想要天花板或地板。与 n/(i^2) 相同。整数除法。下一篇:竞争性编程问题大多无法通过蛮力方法解决。你需要想出数学。最后:竞争性编程的代码质量极差。你应该永远不要拿这样的例子来学习 C++。例如。没有认真的 C++ 开发人员会将变量命名为总和“sm”。这太荒谬了。
  • 我需要 n/(i^2) 的整数除法,并且 sqrt 结果是下限。这不是一个竞争性的编程问题。我从上面提到的链接中改变了问题。我提到的例子是(1)*(10/1)+(4)*(10/4)+(9)*(10/9)=27。关于 c++ 我正在努力学习 cpp 并成为一名 gud 开发人员,感谢您的建议。

标签: c++ algorithm performance sequence square


【解决方案1】:

有什么方法可以加快sm的计算速度?

如果你注意到这种模式并应用一些数学知识,是的。

第一个完美正方形之后的下一个完美正方形(除n==0 之外的所有情况下都是1)将是ceil(sqrt(first number)) 的正方形。

换句话说,说第n个数字的平方根,对应于您的第一个数字将由pow(ceil(sqrt(L)), n)给出。

现在,请注意正方形之间的图案:0 1 4 9 16 25...
0 和 1 的差是 1
1 和 4 之间的差是 3
4 和 9 之间的差是 5
9 和 16 之间的差是 7
16 和 25 的差是 9,以此类推。

这清楚地表明两个完美正方形之间的差始终是奇数。

继续了解这些知识,您需要知道必须添加什么才能获得下一个数字,答案是(sqrt(square) * 2) + 1)

current_square + (sqrt(current_square)*2+1) = next_square

例如,为了证明这个等式,考虑完美的平方 25。应用这个逻辑,下一个完美的平方将是 25 + (sqrt(25) * 2 + 1) = 36,这是正确的。这里 11 与 25 相加,这是一个奇数。

同样,如果您遵循这一趋势,您会发现所有这些数字都是奇数,相差 +2。要找到 2 的下一个平方,您需要将 (sqrt(22)+1) = 5 添加到它 (4+5=9);要找到下一个正方形(即 3),您需要将 (sqrt(32+1) = 7 添加到它 (9+7=16)。差异始终是 +2。

此外,对奇数求和或应用加法在计算上比执行乘法或求每个数的平方根要便宜,因此您的复杂性应该没问题。


然后,执行以下操作:

  • 收集第一个方块。 (理想情况下应该是 1,但如果未提及 n&gt;0 条件,则将条件 if(n!=0) 应用于我的逻辑)
  • 将下一个术语的差异分配为first_square*2+1。不过,您需要添加第一个方格,因为这不是下一个方格,而是下一个方格和当前方格之间的差异。像下面那样在循环中添加术语。
  • 运行一个循环直到您需要的数字。在循环内的变量中收集(square*floor(n/square) 给出的所需总和。
  • 按照我上面提到的方法,即将当前方格添加到next 项(当前方格与下一个方格之间的差)并将下一个方格增加 2。

上述逻辑的一个工作示例:

#include <iostream>
#include <cmath>
#define ll long long 
int main() 
{ 
    ll int n; 
    std::cin>>n;

   // Start from 1: (add case for 0 if input is not >0)
   // you can also start from any other square or define a range.
    ll int first = 1; 

   // Square it:
    ll int first_square = first * first; 

   // Find next square:
    ll int next = (first_square * 2) + 1; 

   // Initialize variable to collect your required sum:
    ll int sum = 0;
    ll int square = first_square;

    while ((square >= 0 && square <= n)) 
    {  
        sum += (square *floor(n/square));

        // Add the perfect square: 
        square += next; 

        // Next odd number to be added:
        next += 2;      
    }     
    std::cout<<sum;  
    return 0; 
} 

【讨论】:

  • 我认为它不会给出正确的结果。你可以看到我提到的例子。对于 n=10 ,平方数是 1,4,9 那么总和是 27 但你的总和是 29
  • @prolific 立即查看。花了很长时间才把它写下来。
  • 上述代码的时间复杂度是否比帖子中的要好?如果是,时间复杂度是多少?
  • 应该少一些,因为它使用了加法,直接检查方块。测试此代码并告诉我。
  • @prolific 这绝对不是更多。它一直运行到 n 但仅适用于正方形,它与您的相似。 (如:10循环运行3次,100循环运行10次,即0(sqrt(n))。将数据类型改为long long。
【解决方案2】:

我们可以使用公式找到直到 n 的所有平方数的总和:

n * (n + 1) * (2*n + 1) / 6

long summation(long n) 
{ 
    return (n * (n + 1) *  
        (2 * n + 1)) / 6; 
} 

【讨论】:

  • 其实它没有回答我的问题?那如何计算上面代码中提到的 sm 值。让我们以 n=10 为例,下面的正方形是 1,4,9。现在 sm 将是 10+8+9=27。但是根据你的回答,我猜 n=10 是 385。
  • @prolific 您的问题陈述是什么?你想计算什么?
  • 我想计算总和( (i^2)*( n / ( i^2 ) ) )。抱歉编辑不佳,我不知道如何在这里使用数学符号。
  • 你遇到问题了吗?
  • @prolific 我了解 sm 计算的内容,但您要解决的实际问题陈述是什么。如果您正在尝试解决家庭作业,请指定整个问题陈述,或者如果您尝试解决的问题有任何链接。
猜你喜欢
  • 1970-01-01
  • 2015-06-30
  • 2017-04-10
  • 2021-11-28
  • 2016-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多