diff --git a/DIRECTORY.md b/DIRECTORY.md index 15283332c..b614bd647 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -142,6 +142,7 @@ * [Gcd Recursive Euclidean](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/gcd_recursive_euclidean.cpp) * [Large Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/large_factorial.cpp) * [Large Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/large_number.h) + * [Lcm Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/lcm_sum.cpp) * [Least Common Multiple](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/least_common_multiple.cpp) * [Miller Rabin](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/miller_rabin.cpp) * [Modular Inverse Fermat Little Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_inverse_fermat_little_theorem.cpp) diff --git a/math/lcm_sum.cpp b/math/lcm_sum.cpp new file mode 100644 index 000000000..34b46020f --- /dev/null +++ b/math/lcm_sum.cpp @@ -0,0 +1,99 @@ +/** + * @file + * @brief An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ + * @details An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ where \f$\mathrm{LCM}(i,n)\f$ + * denotes the Least Common Multiple of the integers i and n. For n greater than or equal to 1. + * The value of the sum is calculated by formula: + * \f[ + * \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d * \mathrm{ETF}(d)) + 1\right) * n\right] + * \f] + * where \mathrm{ETF}(i) represents Euler totient function of i. + * @author [Chesta Mittal](https://github.com/chestamittal) + */ + +#include /// for std::cin and std::cout +#include /// for assert +#include /// for std::vector + +/** + * @namespace math + * @brief Mathematical algorithms + */ +namespace math { + /** + * Function to compute sum of euler totients in sumOfEulerTotient vector + * @param num input number + * @returns int Sum of LCMs, i.e. ∑LCM(i, num) from i = 1 to num + */ + uint64_t lcmSum(const uint16_t& num) { + + uint64_t i=0, j=0; + std::vector eulerTotient(num+1); + std::vector sumOfEulerTotient(num+1); + + // storing initial values in eulerTotient vector + for(i=1; i<=num; i++) { + eulerTotient[i] = i; + } + + // applying totient sieve + for(i=2; i<=num; i++) { + if(eulerTotient[i] == i) { + for(j=i; j<=num; j+=i) { + eulerTotient[j] = eulerTotient[j]/i; + eulerTotient[j] = eulerTotient[j]*(i-1); + } + } + } + + // computing sum of euler totients + for(i=1; i<=num; i++) { + for(j=i; j <=num; j+=i) { + sumOfEulerTotient[j] += eulerTotient[i]*i; + } + } + + return ((sumOfEulerTotient[num] + 1 ) * num) / 2; + } +} // namespace math + +/** + * Function for testing lcmSum function. + * test cases and assert statement. + * @returns `void` +*/ +static void test() { + uint64_t n = 2; + uint64_t test_1 = math::lcmSum(n); + assert(test_1 == 4); + std::cout << "Passed Test 1!" << std::endl; + + n = 5; + uint64_t test_2 = math::lcmSum(n); + assert(test_2 == 55); + std::cout << "Passed Test 2!" << std::endl; + + n = 10; + uint64_t test_3 = math::lcmSum(n); + assert(test_3 == 320); + std::cout << "Passed Test 3!" << std::endl; + + n = 11; + uint64_t test_4 = math::lcmSum(n); + assert(test_4 == 616); + std::cout << "Passed Test 4!" << std::endl; + + n = 15; + uint64_t test_5 = math::lcmSum(n); + assert(test_5 == 1110); + std::cout << "Passed Test 5!" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // execute the tests + return 0; +}