Project Euler : First Triangle Number To Have Over Five Hundred Divisors

This was solved by brute force. I implemented a method to find the number of factors of a number by its prime factorization. Having already built up a sieve method to quickly get primes, the number of factors can be found faster this way.

PrimeNumber class:

package pba.common.number;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

public class PrimeNumbers {
	private List<Integer> m_primeNumbers;

	/**
	 * @param sizeOfSieve The upper bound to the determination of prime numbers.
	 */
	public PrimeNumbers(int sizeOfSieve) {
		m_primeNumbers = new ArrayList<Integer>();
		sieveOfEratosthenes(sizeOfSieve);
	}

	/**
	 * Calculates the number of factors for a given number by prime factorization. For example, <br>
	 * 28 = 2^2 * 7 <br>
	 * Thus the number of factors of 28 are (2+1)*(1+1) = 6.
	 *
	 * @param number The number whose number of factors are required
	 * @return The number of factors the given number has
	 */
	public int getNumberOfFactors(int number) {
		int numberOfFactors = 1;
		for (int prime : m_primeNumbers) {
			int exponent = 0;
			while (number % prime == 0) {
				exponent++;
				number /= prime;
			}
			numberOfFactors *= exponent + 1;
		}

		return numberOfFactors;
	}

	/**
	 * Finds the primes using the SieveOfEratosthenes method
	 *
	 * @param sizeOfSieve The upper bound till which the primes are to be calculated
	 */
	private void sieveOfEratosthenes(int sizeOfSieve) {
		m_primeNumbers.add(2);
		BitSet primeBits = new BitSet(sizeOfSieve / 2);
		int primeNumberIndex = primeBits.nextClearBit(0);
		int primeNumber = 2 * primeNumberIndex + 3;
		while (primeNumber < sizeOfSieve) {
			m_primeNumbers.add(primeNumber);
			for (int i = primeNumberIndex; i < sizeOfSieve / 2; i += primeNumber)
				primeBits.set(i);
			primeNumberIndex = primeBits.nextClearBit(primeNumberIndex);
			primeNumber = 2 * primeNumberIndex + 3;
		}
	}
}

Main class:

package problems_11_20;

import pba.common.number.PrimeNumbers;

public class Problem_12 {
	public static void mainAnuvrat(String[] args) {
		PrimeNumbers p = new PrimeNumbers(1000000);

		int triangleNumber = 1;
		int step = 1;
		while (p.getNumberOfFactors(triangleNumber) < 500)
			triangleNumber += ++step;

		System.out.println(triangleNumber);
	}

	public static void mainProjectEuler(String[] args) {
		PrimeNumbers p = new PrimeNumbers(1000000);

		boolean odd = true;
		int n = 1;
		int numberOfFactors = 0;
		int memoization = 1;
		do {
			if (odd) {
				int temp = p.getNumberOfFactors((n + 1) / 2);
				numberOfFactors = memoization * temp;
				memoization = temp;
			} else {
				int temp = p.getNumberOfFactors(n + 1);
				numberOfFactors = memoization * temp;
				memoization = temp;
			}
			odd = !odd;
			n++;
		} while (numberOfFactors < 500);
		n--;

		System.out.println(n * (n + 1) / 2);
	}
}

Project Euler did suggest an improvement on this. It says that since

t = \frac{n \times (n+1)}{2}

and n, n+1 being co-primes, the number of divisors can be found as

D(t) = D(n) \times D(\frac{n+1}{2}) if n is odd

D(t) = D(\frac{n}{2}) \times D(n+1) if n is even

This provides a lot of advantage over the previous implementation. The first being that we are now looking to find the number of factors for a smaller numbers. Secondly, the value for the n+1 can be used in the next triangle number, thus saving more computations.

Popularity: 42% [?]

Related posts:

  1. Project Euler : Quadratic Producing Longest Prime Sequence
  2. Project Euler : Largest N Digit Pandigital Prime Number
  3. Sum Of Divisors
  4. Project Euler : Verifying Triangle Words
  5. Project Euler : Find the nth Prime