找到1和N之间的所有数字的总和,可以用x或y整除

时间:2010-12-17 05:28:13

标签: c++ c algorithm puzzle

假设我们3号码Nxy始终为>=1

N将大于xyx将大于y

现在我们需要找到1到N之间所有数字的总和,它们可以被x或y 整除。

我想出了这个:

sum = 0;
for(i=1;i<=N;i++)
{
  if(i%x || i%y)
    sum += i;
}

有没有更好的方法来找到避免for循环的总和?

我现在已经好好打了好几天但是没有更好的东西。

如果N的值有上限,我们可以使用查找方法来加速该过程。

谢谢大家。

我想要一个基于C / C ++的解决方案。是否有内置函数来执行此操作?或者我必须编写算法代码?

2 个答案:

答案 0 :(得分:27)

是。你可以完全取消for循环,并在恒定时间内找到总和。

根据Inclusion–exclusion principle总结x的倍数和y的倍数,并减去已添加两次的常见倍数应该给出我们所需的金额。

Required Sum = sum of ( multiples of x that are <= N ) +      
               sum of ( multiples of y that are <= N ) -
               sum of ( multiples of (x*y) that are <= N )

示例:

N = 15
x = 3
y = 4

Required sum = ( 3 + 6 + 9 + 12 + 15) +  // multiples of 3
               ( 4 + 8 + 12 ) -          // multiples of 4
               ( 12 )                    // multiples of 12

如上所示,我们不得不减去12,因为它是一个常见的倍数。

整个算法O(1)如何?

sum(x, N)x的倍数之和,其小于或等于N

sum(x,N) = x + 2x + ... + floor(N/x) * x
         = x * ( 1 + 2 + ... + floor(N/x) )
         = x * ( 1 + 2 + ... + k)    // Where k = floor(N/x)
         = x * k * (k+1) / 2         // Sum of first k natural num = k*(k+1)/2

现在可以在恒定时间内计算k = floor(N/x)

知道ksum(x,N)可以在固定时间内计算。

因此,所需的总和也可以在恒定时间内计算。

修改

仅当xyco-primes时,上述讨论才适用。如果不是,我们需要使用LCM(x,y)代替x*y。有许多方法可以找到LCM,其中一种方法是通过GCD划分产品。现在GCD不能在恒定时间内计算,但其time complexity可以显着小于线性时间。

答案 1 :(得分:4)

如果一个数字可被X整除,则它必须是x的倍数。 如果一个数字可被Y整除,则它必须是y的倍数。

我相信,如果你对x和y的所有倍数进行for循环,并避免重复,你应该得到相同的答案。

从我的脑海中,出现了类似的东西:

sum = 0
for( i=x; i<=n; i+=x)
    sum += i;

for( i=y; i<=n; i+=y)
    if( y % x != 0 )
        sum += i;