将条件求和转换为闭合形式解

时间:2016-05-27 09:15:26

标签: algorithm math

通常可以将求和转换为封闭形式的解决方案。

例如

for (int i=0;i<n;i++)
  result += i;

相当于result += max(0, n * ( n - 1) / 2)

for (int i=0;i<n;i++)
  for (int j=0;j<m;j++)
    result += i;

相当于result += max(0, m * n * ( n - 1) / 2)

for (int i=0;i<n;i++)
  for (int j=0;j<m;j++)
    if (i < j)
      result += i;

相当于

for (int i=0;i<n;i++)
  for (int j=i+1;j<m;j++)
     result += i;

因此相当于

for (int i=0;i<n;i++)
  if (i+1 < m)
     result += i * (m-i);

因此相当于

for (int i=0;i<min(n,m-1);i++)
     result += m * i - i * i;

因此最终等同于result += max(0, m * min(n,m-1) * (min(n,m-1) - 1) / 2 - (min(n,m-1) - 1) * ((min(n,m-1) - 1) + 1) * (2 * (min(n,m-1) - 1) + 1) / 6)或者更容易写成result += max(0, m <= n ? m * (m-1) * ((m-1) - 1) / 2 - ((m-1) - 1) * (((m-1) - 1) + 1) * (2 * ((m-1) - 1) + 1) / 6) : m * n * (n - 1) / 2 - (n - 1) * ((n - 1) + 1) * (2 * (n - 1) + 1) / 6)

何时可以转换为封闭式解决方案?

似乎,如果只允许条件,加法和乘法(即多项式),则始终可以从最内圈开始,跟踪允许的最小值/最大值和添加的多项式的范围。

但是,手动执行此转换非常容易出错并且耗费时间,因为范围在每个循环中被分割并且呈指数增长。

是否有工具可以从迭代版本自动生成封闭形式的解决方案?

当允许分裂时,它变得多难?

for (int i=2;i<n;i++)
  if (i % 2 == 0) 
    result += 1;

for (int i=2;i<n;i+=2) result += 1;相当容易,相当于max(0, (n/2) * (n/2 + 1) )

另一方面

for (int i=2;i<n;i++)
  if (n % i == 0) 
    result += 1;

似乎很难改变。

1 个答案:

答案 0 :(得分:1)

虽然有许多总和的封闭形式表达式,但也有许多其他的,没有人能够找到一个,如谐波数(注意这些总和的数量取决于你允许的功能)封闭形式)。

  

看来,如果只允许条件,加法和乘法(即多项式),总是可以从最里面的循环开始,跟踪允许的最小值/最大值和添加的多项式的范围。

你几乎是对的,如果条件只影响求和的参数(第一个或最后一个术语,或可能的步长,如if (i % 2 == 0)),那么总会有一个封闭的形式,可以表示为有理函数。除其他表达式外,这些表达式可以使用例如finite calculus来计算。

对于更广泛的表达式,您可以使用generating functions(请参阅第17.2.2节以获得非常温和的介绍)。这些可以在很大程度上用于计算某些表达式的闭合形式(总和或重复关系)。

  

当允许分裂时,它变得多难?

正如我所说,if (i % 2 == 0)相当容易,因为它只是增加总和的步长,例如

for (int i = 0; i <= n; i++)
  if (i % 2 == 0) 
    result += i;

有效地成为

for (int i = 0; i <= n/2; i++)
  result += 2*i;

非常适合n的封闭形式。其他条件,例如您提供的if (n % i == 0),将会更加艰难。例如,考虑非常相似的表达式,它计算除数的总和

for (int i = 1; i < n; i++)
  if (n % i == 0)
    result += i;

如果它允许一个封闭的表格表达式,那么这很容易被用来用两个素数除数来计算数字,这通常被认为很难。