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);
}
};