2023/10/17

84 阅读2分钟

2652. 倍数求和

算法掌握:

  • 遍历
  • 取模,或运算

解题思路:

朴素法直接暴力循环每次判断是否满足是3,5或7的倍数,就累加即可

数学推导->首先,根据等差数列的求和公式,可以得到3的倍数的和为(3 + m) * cnt / 2,其中m是小于等于n的最大3的倍数,cnt是元素个数。同样地,可以计算出5和7的倍数的和。

然而,由于存在一些既是3的倍数又是5或7的倍数的数,这些数在计算3的倍数和和5的倍数和时被计算了两次,因此需要将其扣除。这样的数满足同时是15的倍数,因此需要计算15的等差数列和。

同理,还需要计算出既是3的倍数又是7的倍数以及既是5的倍数又是7的倍数的数的等差数列和。记为s4、s5和s6。

最后,还需要将同时是3、5和7的倍数的数的倍数和去除,这个数是357的倍数,记为s7。

最终的答案应该是s1 + s2 + s3 - s4 - s5 - s6 + s7。这个过程类似于使用容器原理计算图形的面积:S = S(A) + S(B) + S(C) - S(A ∩ B) - S(A ∩ C) - S(B ∩ C) + S(A ∩ B ∩ C)。

java code:

class Solution {
    public int sumOfMultiples(int n) {
        int res = 0;
        for(int i = 1; i <= n; i++){
            if(i % 3 == 0 || i % 5 == 0 || i % 7 == 0){
                res += i;
            }
        }
        return res;
    }
}
class Solution {
    public int sumOfMultiples(int n) {
        return f(n, 3) + f(n, 5) + f(n, 7) - f(n, 3 * 5) - f(n, 3 * 7) - f(n, 5 * 7) + f(n, 3 * 5 * 7);
    }

    int f(int n, int k){
        // cnt * k 为小于等于n的最大数字
        int cnt = n / k;  
        // 等差数列求和公式  
        return (k + cnt * k) * cnt / 2; 
    }
}

c++code:

class Solution {
public:
    int sumOfMultiples(int n) {
        int res = 0;
        for(int i = 1; i <= n; i++){
            if(i % 3 == 0 || i % 5 == 0 || i % 7 == 0){
                res += i;
            }
        }
        return res;
    }

};
class Solution {
public:
    int f(int n, int k){
        // cnt * k 为小于等于n的最大数字
        int cnt = n / k;  
        // 等差数列求和公式  
        return (k + cnt * k) * cnt / 2; 
    }

    int sumOfMultiples(int n) {
        return f(n, 3) + f(n, 5) + f(n, 7) - f(n, 3 * 5) - f(n, 3 * 7) - f(n, 5 * 7) + f(n, 3 * 5 * 7);
    }
};