Tim Varley Logo
Tim Varley Principal AI Engineer and Tech Leader
Problem #21 hard

Amicable Numbers

Let d(n)d(n) be defined as the sum of proper divisors of nn (numbers less than nn which divide evenly into nn). If d(a)=bd(a) = b and d(b)=ad(b) = a, where aba \ne b, then aa and bb are an amicable pair and each of aa and bb are called amicable numbers.

For example, the proper divisors of 220220 are 1,2,4,5,10,11,20,22,44,551, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110110; therefore d(220)=284d(220) = 284. The proper divisors of 284284 are 1,2,4,711, 2, 4, 71 and 142142; so d(284)=220d(284) = 220.

Evaluate the sum of all the amicable numbers under 1000010000.

View on Project Euler

Implementations

cpp
// Answer: 31626
#include <iostream>
int amicable_numbers_sum(int max)
{
int a = 0;
int b = 0;
int amic_sum = 0;
for( int i = 1; i <= max ;i++){
// std::cout << "i: " << i << std::endl;
a = 0;
for(int j = 1 ; j < i ; j++){
if( 0 == (i%j)){
a += j;
}
}
b = 0;
for( int k = 1 ; k < a ; k++ ){
// std::cout << "k: " << k << std::endl;
if( 0 == (a%k)){
b += k;
}
}
if( b == i && b != a ){
amic_sum += i;
}
// std::cout << "Sum A: " << a << std::endl;
// std::cout << "Sum B: " << b << std::endl;
// std::cout << "Amic: " << amic_sum << std::endl;
}
return amic_sum;
}
#if ! defined UNITTEST_MODE
int main(int argc, char const *argv[]) {
std::cout << "Answer: " << amicable_numbers_sum(10000) << std::endl;
}
#endif //#if ! defined UNITTEST_MODE
View on GitHub
O(n) time complexity

Solution Notes

Mathematical Background

Amicable numbers are pairs of numbers where each number is the sum of the proper divisors of the other. Proper divisors of a number nn are all positive divisors of nn except nn itself.

For example:

  • d(220)=1+2+4+5+10+11+20+22+44+55+110=284d(220) = 1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284
  • d(284)=1+2+4+71+142=220d(284) = 1 + 2 + 4 + 71 + 142 = 220

The amicable pairs under 10,000 are: (220, 284), (1184, 1210), (2620, 2924), (5020, 5564), (6232, 6368).

The sum of all amicable numbers under 10,000 is 31,626.

Algorithm Analysis

Divisor sum computation: For each number from 1 to 9,999, calculate the sum of its proper divisors.

Optimization techniques:

  • Sieve-like approach: Pre-compute divisor sums for all numbers up to 10,000 using a single pass
  • Memoization: Store computed divisor sums to avoid recomputation
  • Efficient divisor finding: For each number i, add i to the divisor sum of all multiples j×i ≤ 10,000

Amicable pair detection: For each number a, compute b = d(a), then check if d(b) = a and a ≠ b.

Time complexity is O(MAX × log MAX) due to divisor enumeration. Space complexity is O(MAX) for storing divisor sums.

Key Insights

  • Amicable pairs come in pairs, so each pair contributes both numbers to the sum
  • Perfect numbers (where d(n) = n) are excluded since a ≠ b
  • The search space is limited to numbers under 10,000
  • There are only 5 amicable pairs under 10,000
  • Optimization is crucial due to the nested divisor computations
  • This demonstrates number theory applications in programming

Educational Value

This problem teaches:

  • Number theory and divisor function properties
  • Efficient divisor enumeration algorithms
  • Optimization through pre-computation and memoization
  • Detecting mathematical relationships through computation
  • Handling symmetric relationships in data structures
  • The connection between pure mathematics and computational methods
  • When to use brute force versus optimized approaches