2652. 倍数求和

发布时间 2023-10-17 10:31:31作者: DawnTraveler

1.题目介绍

2.题解

2.1 枚举

思路

直接从[1,n]进行一次遍历,判断出能被整除的数便加到一个变量result中

代码

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

代价

时间复杂度:O(n)。
空间复杂度:O(1)。

2.2 容斥原理

思路

找到所有能被3整除的数并求和,同理分别找到所有能被5,7整除的数并求和;这里就会存在一个问题,重复求和了同时能被3,5,7其中两个或三个整除的数,需要减除重复的
综合一下分析,考虑在区间 [1,n]内能被数 m 整除的整数,从小到大排序后成为一个等差数列,和为:\(f(n,m)=\frac{(m+m\times\lfloor\frac nm\rfloor)\times\lfloor\frac nm\rfloor}2\)
根据 容斥原理,在区间 [1,n] 内,能被 3、5和 7 整除的整数之和为:\(f(n,3)+f(n,5)+f(n,7)-f(n,3\times5)-f(n,3\times7)-f(n,5\times7)+f(n,3\times5\times7)\)

代码

class Solution {
public:
    int sumOfMultiples(int n) {
        int result = 0;
        return sumDividerNum(n,3) + sumDividerNum(n,5) + sumDividerNum(n,7) - sumDividerNum(n,3*5) - sumDividerNum(n,3*7) - sumDividerNum(n,5*7) + sumDividerNum(n, 3*5*7);
    }

    int sumDividerNum(int n, int m){
        return (m+m*(n/m))*(n/m)/2;
    }
};

代价

时间复杂度:O(1)。
空间复杂度:O(1)。