用公式替换循环

时间:2010-04-09 18:26:57

标签: c math

我有一个在O(end-start)中运行的循环,我想用O(1)替换它。
如果“宽度”不会减少,那将非常简单。

for (int i = start; i <= end; i++, width--)
    if (i % 3 > 0) // 1 or 2, but not 0
        z += width;

开始,结束和宽度具有正值

7 个答案:

答案 0 :(得分:2)

请注意

width == initial_width - (i - start)

所以求和可以改写为

      end
     —————
     \      (initial_width + start - i)
     /
     —————
    i=start
  i mod 3 ≠ 0

      end                                   ⌊end/3⌋
     —————                                   —————
==   \      (initial_width + start - i)  ——  \      (initial_width + start - 3j)
     /                                       /
     —————                                   —————
    i=start                               j=⌈start/3⌉

其余的应该很简单。

答案 1 :(得分:2)

正如其他人提到的,这可能是最容易被认为是两个系列的总和。

   x     x+3       x+6      ...  x+3N
 + x+3N  x+3(N-1)  x+3(N-2) ...  x
  -----------------------------------
  2x+3N 2x+3N     2x+3N     ... 2x+3N

以上可以简化为       (2X + 3N)(N + 1)

这意味着其中一个的总和真的......       (2X + 3N)(N + 1)/ 2

这个等式需要适用于两个系列。两者的N可能不同。

因此,您所要做的就是确定您的起点和系列中的项目数。这应留给学生练习。

希望这有帮助。

答案 2 :(得分:1)

将这视为两个单独系列的总和可能最容易,一个用于i%3 = 1,另一个用于i%3=2。或者,您可以将其视为i的所有值减去i%3=0的总和的总和。为了论证,让我们看看后一种方法的前半部分:总结所有宽度值。

在这种情况下,width将从某个初始值开始,每次迭代其值将减少1.在最后一次迭代中,其值将减少(end-start)。也许最容易将其视为三角形。为了简单起见,我们将使用较小的数字 - 我们将从width = 5,start = 1和end = 5开始。也许最简单的绘制图表:

宽度值:

*
**
***
****
*****

我们真正想要的是那个三角形的面积 - 这是一个非常着名的基本几何公式 - 1 / 2ab,其中a和b是两边的长度(在这种情况下) ,由widthend-start的初始值定义。这假设它确实是一个三角形 - 即它减少到0.实际上,我们很有可能处理一个截断的三角形 - 但其公式也是众所周知的(1 / 2a < sub> 1 b + 1 / 2a 2 b,其中a是右侧和左侧的高度,b是宽度。

答案 3 :(得分:1)

我想出了这个丑陋的方法:

int start; // = some number
int end; // = ...

int initialwidth; // = ...

int each = (end+1)/3 - (start-1)/3 - 1;
int loop = 2*(3-(start+2)%3)+1;
int total = each*loop + 3*each*(each-1) + (start%3==1) + (end-start)*(end%3==1);

int result = -total + initialwidth*(1 + end - start - end/3 + (start-1)/3);

总计将给出i =开始结束时(i%3> 0)的总和(i-start)s。

结果将给出添加到z的宽度总和。

答案 4 :(得分:1)

和(i = 1 ... n)i的闭合形式是(n)(n + 1)/ 2。你应该可以用一个小代数来找到一个封闭的表格,为你提供你正在寻找的结果。

答案 5 :(得分:0)

你想要像z = 2 * width * (start - end) / 3 + (start - end) % 3这样的东西吗? (不太对,但足够接近让你走上正确的轨道。

答案 6 :(得分:0)

这不是一个完整的答案,但你应该注意到:

x = end - start;
k = ~(-1 << x); // I think (width * k)>>x would be your z except if you didn't have the contidional

并且从LSB向上设置两个位,一位清零,两位设置,一位清零(0x ... 011011011)的值可用于计算%3为0的位置。

R = k - (k & 0x...011011011); // This is the series 3 + (3 << 3) + (3 << 6) ...

z = (R * width)>>x;  // I think.

只是尝试一下。我可能犯了一些错误。