Open in App
Not now

# Find Landau’s function for a given number N

• Last Updated : 07 Mar, 2023

Given an integer N, the task is to find the Landau’s Function of the number N.

In number theory, The Landau’s function finds the largest LCM among all partitions of the given number N.

For Example: If N = 4, then possible partitions are:
1. {1, 1, 1, 1}, LCM = 1
2. {1, 1, 2}, LCM = 2
3. {2, 2}, LCM = 2
4. {1, 3}, LCM = 3

Among the above partitions, the partitions whose LCM is maximum is {1, 3} as LCM  = 3.

Examples:

Input: N = 4
Output: 4
Explanation:
Partitions of 4 are [1, 1, 1, 1], [1, 1, 2], [2, 2], [1, 3], [4] among which maximum LCM is of the last partition 4 whose LCM is also 4.

Input: N = 7
Output: 12
Explanation:
For N = 7 the maximum LCM is 12.

### A slower (but easier to understand) algorithm

Approach: The idea is to use Recursion to generate all possible partitions for the given number N and find the maximum value of LCM among all the partitions. Consider every integer from 1 to N such that the sum N can be reduced by this number at each recursive call and if at any recursive call N reduces to zero then find the LCM of the value stored in the vector. Below are the steps for recursion:

1. Get the number N whose sum has to be broken into two or more positive integers.
2. Recursively iterate from value 1 to N as index i:
• Base Case: If the value called recursively is 0, then find the LCM of the value stored in the current vector as this is the one of the way to broke N into two or more positive integers.

```if (n == 0)
findLCM(arr);```
• Recursive Call: If the base case is not met, then Recursively iterate from [i, N – i]. Push the current element j into vector(say arr) and recursively iterate for the next index and after the this recursion ends then pop the element j inserted previously:

```for j in range[i, N]:
arr.push_back(j);
recursive_function(arr, j + 1, N - j);
arr.pop_back(j);```
1. After all the recursive call, print the maximum of all the LCM calculated.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach` `#include ` `using` `namespace` `std;`   `// To store Landau's function of the number` `int` `Landau = INT_MIN;`   `// Function to return gcd of 2 numbers` `int` `gcd(``int` `a, ``int` `b)` `{`   `    ``if` `(a == 0)`   `        ``return` `b;`   `    ``return` `gcd(b % a, a);` `}`   `// Function to return LCM of two numbers` `int` `lcm(``int` `a, ``int` `b)` `{` `    ``return` `(a * b) / gcd(a, b);` `}`   `// Function to find max lcm value` `// among all representations of n` `void` `findLCM(vector<``int``>& arr)` `{` `    ``int` `nth_lcm = arr[0];`   `    ``for` `(``int` `i = 1; i < arr.size(); i++)`   `        ``nth_lcm = lcm(nth_lcm, arr[i]);`   `    ``// Calculate Landau's value` `    ``Landau = max(Landau, nth_lcm);` `}`   `// Recursive function to find different` `// ways in which n can be written as` `// sum of atleast one positive integers` `void` `findWays(vector<``int``>& arr, ``int` `i, ``int` `n)` `{` `    ``// Check if sum becomes n,` `    ``// consider this representation` `    ``if` `(n == 0)` `        ``findLCM(arr);`   `    ``// Start from previous element` `    ``// in the representation till n` `    ``for` `(``int` `j = i; j <= n; j++) {`   `        ``// Include current element` `        ``// from representation` `        ``arr.push_back(j);`   `        ``// Call function again` `        ``// with reduced sum` `        ``findWays(arr, j, n - j);`   `        ``// Backtrack - remove current` `        ``// element from representation` `        ``arr.pop_back();` `    ``}` `}`   `// Function to find the Landau's function` `void` `Landau_function(``int` `n)` `{` `    ``vector<``int``> arr;`   `    ``// Using recurrence find different` `    ``// ways in which n can be written` `    ``// as a sum of atleast one +ve integers` `    ``findWays(arr, 1, n);`   `    ``// Print the result` `    ``cout << Landau;` `}`   `// Driver Code` `int` `main()` `{` `    ``// Given N` `    ``int` `N = 4;`   `    ``// Function Call` `    ``Landau_function(N);` `    ``return` `0;` `}`

## Java

 `// Java program for the above approach` `import` `java.util.*;`   `class` `GFG{`   `// To store Landau's function of the number` `static` `int` `Landau = Integer.MIN_VALUE;`   `// Function to return gcd of 2 numbers` `static` `int` `gcd(``int` `a, ``int` `b)` `{` `    ``if` `(a == ``0``)` `        ``return` `b;`   `    ``return` `gcd(b % a, a);` `}`   `// Function to return LCM of two numbers` `static` `int` `lcm(``int` `a, ``int` `b)` `{` `    ``return` `(a * b) / gcd(a, b);` `}`   `// Function to find max lcm value` `// among all representations of n` `static` `void` `findLCM(Vector arr)` `{` `    ``int` `nth_lcm = arr.get(``0``);`   `    ``for``(``int` `i = ``1``; i < arr.size(); i++)` `        ``nth_lcm = lcm(nth_lcm, arr.get(i));`   `    ``// Calculate Landau's value` `    ``Landau = Math.max(Landau, nth_lcm);` `}`   `// Recursive function to find different` `// ways in which n can be written as` `// sum of atleast one positive integers` `static` `void` `findWays(Vector arr, ` `                     ``int` `i, ``int` `n)` `{` `    `  `    ``// Check if sum becomes n,` `    ``// consider this representation` `    ``if` `(n == ``0``)` `        ``findLCM(arr);`   `    ``// Start from previous element` `    ``// in the representation till n` `    ``for``(``int` `j = i; j <= n; j++)` `    ``{` `        `  `        ``// Include current element` `        ``// from representation` `        ``arr.add(j);`   `        ``// Call function again` `        ``// with reduced sum` `        ``findWays(arr, j, n - j);`   `        ``// Backtrack - remove current` `        ``// element from representation` `        ``arr.remove(arr.size() - ``1``);` `    ``}` `}`   `// Function to find the Landau's function` `static` `void` `Landau_function(``int` `n)` `{` `    ``Vector arr = ``new` `Vector<>();`   `    ``// Using recurrence find different` `    ``// ways in which n can be written` `    ``// as a sum of atleast one +ve integers` `    ``findWays(arr, ``1``, n);`   `    ``// Print the result` `    ``System.out.print(Landau);` `}`   `// Driver Code` `public` `static` `void` `main(String[] args)` `{` `    ``// Given N` `    ``int` `N = ``4``;`   `    ``// Function call` `    ``Landau_function(N);` `}` `}`   `// This code is contributed by amal kumar choubey`

## Python3

 `# Python3 program for the above approach` `import` `sys`   `# To store Landau's function of the number` `Landau ``=` `-``sys.maxsize ``-` `1`   `# Function to return gcd of 2 numbers` `def` `gcd(a, b):`   `    ``if` `(a ``=``=` `0``):` `        ``return` `b` `        `  `    ``return` `gcd(b ``%` `a, a)`   `# Function to return LCM of two numbers` `def` `lcm(a, b):` `    `  `    ``return` `(a ``*` `b) ``/``/` `gcd(a, b)`   `# Function to find max lcm value` `# among all representations of n` `def` `findLCM(arr):`   `    ``global` `Landau`   `    ``nth_lcm ``=` `arr[``0``]`   `    ``for` `i ``in` `range``(``1``, ``len``(arr)):` `        ``nth_lcm ``=` `lcm(nth_lcm, arr[i])`   `    ``# Calculate Landau's value` `    ``Landau ``=` `max``(Landau, nth_lcm)` `    `  `# Recursive function to find different` `# ways in which n can be written as` `# sum of atleast one positive integers` `def` `findWays(arr, i, n):`   `    ``# Check if sum becomes n,` `    ``# consider this representation` `    ``if` `(n ``=``=` `0``):` `        ``findLCM(arr)`   `    ``# Start from previous element` `    ``# in the representation till n` `    ``for` `j ``in` `range``(i, n ``+` `1``):`   `        ``# Include current element` `        ``# from representation` `        ``arr.append(j)`   `        ``# Call function again` `        ``# with reduced sum` `        ``findWays(arr, j, n ``-` `j)`   `        ``# Backtrack - remove current` `        ``# element from representation` `        ``arr.pop()` `    `  `# Function to find the Landau's function` `def` `Landau_function(n):`   `    ``arr ``=` `[]`   `    ``# Using recurrence find different` `    ``# ways in which n can be written` `    ``# as a sum of atleast one +ve integers` `    ``findWays(arr, ``1``, n)`   `    ``# Print the result` `    ``print``(Landau)`   `# Driver Code`   `# Given N` `N ``=` `4`   `# Function call` `Landau_function(N)`   `# This code is contributed by chitranayal`

## C#

 `// C# program for the above approach` `using` `System;` `using` `System.Collections.Generic;`   `class` `GFG{`   `// To store Landau's function of the number` `static` `int` `Landau = ``int``.MinValue;`   `// Function to return gcd of 2 numbers` `static` `int` `gcd(``int` `a, ``int` `b)` `{` `    ``if` `(a == 0)` `        ``return` `b;`   `    ``return` `gcd(b % a, a);` `}`   `// Function to return LCM of two numbers` `static` `int` `lcm(``int` `a, ``int` `b)` `{` `    ``return` `(a * b) / gcd(a, b);` `}`   `// Function to find max lcm value` `// among all representations of n` `static` `void` `findLCM(List<``int``> arr)` `{` `    ``int` `nth_lcm = arr[0];`   `    ``for``(``int` `i = 1; i < arr.Count; i++)` `        ``nth_lcm = lcm(nth_lcm, arr[i]);`   `    ``// Calculate Landau's value` `    ``Landau = Math.Max(Landau, nth_lcm);` `}`   `// Recursive function to find different` `// ways in which n can be written as` `// sum of atleast one positive integers` `static` `void` `findWays(List<``int``> arr, ` `                     ``int` `i, ``int` `n)` `{` `    `  `    ``// Check if sum becomes n,` `    ``// consider this representation` `    ``if` `(n == 0)` `        ``findLCM(arr);`   `    ``// Start from previous element` `    ``// in the representation till n` `    ``for``(``int` `j = i; j <= n; j++)` `    ``{` `        `  `        ``// Include current element` `        ``// from representation` `        ``arr.Add(j);`   `        ``// Call function again` `        ``// with reduced sum` `        ``findWays(arr, j, n - j);`   `        ``// Backtrack - remove current` `        ``// element from representation` `        ``arr.RemoveAt(arr.Count - 1);` `    ``}` `}`   `// Function to find the Landau's function` `static` `void` `Landau_function(``int` `n)` `{` `    ``List<``int``> arr = ``new` `List<``int``>();`   `    ``// Using recurrence find different` `    ``// ways in which n can be written` `    ``// as a sum of atleast one +ve integers` `    ``findWays(arr, 1, n);`   `    ``// Print the result` `    ``Console.Write(Landau);` `}`   `// Driver Code` `public` `static` `void` `Main(String[] args)` `{` `    `  `    ``// Given N` `    ``int` `N = 4;`   `    ``// Function call` `    ``Landau_function(N);` `}` `}`   `// This code is contributed by amal kumar choubey`

## Javascript

 ``

Output:

`4`

Time Complexity: O(2N
Auxiliary Space: O(N2

### A faster algorithm

Lemma. There is an optimal answer where every number in partition is either 1 or of form p^a, where p is prime.

Proof. Suppose that in an optimal partition we have some n which has more than one prime factors. Then we can write n=mk, where gcd(m, k) = 1 and m>1 and k>1. Here we should note than mk  m+k, so (mk – m – k)  0. So let’s remove n from partition and replace it with m and k and (mk – m – k) 1’s (example : […, 12, …] -> […, 3 4 1 1 1 1 1, …]).  The sum of the array hasn’t changed, so it is still a partition of n, and the lcm, obviously, hasn’t changed. So it is still an optimal partition. We do that replacement several times until there is no number with >1 prime factors. QED

Lets define a function g(n, p), where n is prime, as the optimal answer where all numbers only consist of primes which are less than p. (Example: g(4, 3) = 4. The optimal answer is [2^2]. Note that the answer [2, 3] doesn’t count since 3p). Let’s also say that g(0, p) = 1 and g(n, 2) = 1 so it’s a bit easier for us.

Then we can write a recursive formula for g(n, p):

g(n, p) is maximum of:

• g(n, prev. prime of p) – we add nothing and restrict all next primes to be less than prev. prime of p
• g(n – p, prev. prime of p)*p – we add p and restrict all next primes to be less than prev. prime of p
• g(n – p^2, prev. prime of p)*p^2 – we add p^2 and restrict all next primes to be less than prev. prime of p
• g(n – p^3, prev. prime of p)*p^3 – we add p^3 and restrict all next primes to be less than prev. prime of p
• etc…

So g(n, min prime which is >n) is our answer. We can get the answer by using dynamic programming.

## C++

 `#include ` `#include ` `using` `namespace` `std;`   `int` `main()` `{` `    ``int` `n = 4;`   `    ``vector<``int``> primes;` `    ``vector<``int``> max_prime(2 * n + 1, 0);` `    ``for` `(``int` `i = 2; i <= 2 * n; ++i) {` `        ``if` `(max_prime[i] == 0) {` `            ``max_prime[i] = i;` `            ``primes.push_back(i);` `        ``}` `        ``for` `(``int` `j = 0;` `             ``j < primes.size() && primes[j] <= max_prime[i]` `             ``&& 1ll * primes[j] * i <= 2 * n;` `             ``++j) {` `            ``max_prime[primes[j] * i] = max_prime[i];` `        ``}` `    ``}` `    ``vector > g(` `        ``n + 1, vector<``long` `long``>(primes.size() + 1, 1ll));` `    ``for` `(``int` `p = 1; p <= primes.size(); ++p) {` `        ``for` `(``int` `i = 0; i <= n; ++i) {` `            ``g[i][p] = g[i][p - 1];` `            ``long` `long` `power = primes[p - 1];` `            ``while` `(power <= i) {` `                ``long` `long` `new_option` `                    ``= g[i - power][p - 1] * power;` `                ``g[i][p] = max(g[i][p], new_option);` `                ``power *= primes[p - 1];` `            ``}` `        ``}` `    ``}` `    ``cout << g[n][primes.size()] << endl;` `    ``return` `0;` `}`

## Java

 `import` `java.util.*;` `import` `java.math.*;`   `public` `class` `Main {` `    ``public` `static` `void` `main(String[] args) {` `        ``int` `n = ``4``;` `        ``List primes = ``new` `ArrayList<>();` `        ``int``[] maxPrime = ``new` `int``[``2` `* n + ``1``];` `        ``Arrays.fill(maxPrime, ``0``);` `        ``for` `(``int` `i = ``2``; i <= ``2` `* n; ++i) {` `            ``if` `(maxPrime[i] == ``0``) {` `                ``maxPrime[i] = i;` `                ``primes.add(i);` `            ``}` `            ``for` `(``int` `j = ``0``; j < primes.size() && primes.get(j) <= maxPrime[i]` `                    ``&& (``long``) primes.get(j) * i <= ``2` `* n; ++j) {` `                ``maxPrime[primes.get(j) * i] = maxPrime[i];` `            ``}` `        ``}` `        ``long``[][] g = ``new` `long``[n + ``1``][primes.size() + ``1``];` `        ``for` `(``int` `i = ``0``; i <= n; ++i) {` `            ``Arrays.fill(g[i], ``1``);` `        ``}` `        ``for` `(``int` `p = ``1``; p <= primes.size(); ++p) {` `            ``for` `(``int` `i = ``0``; i <= n; ++i) {` `                ``g[i][p] = g[i][p - ``1``];` `                ``int` `power = primes.get(p - ``1``);` `                ``while` `(power <= i) {` `                    ``long` `newOption = g[i - power][p - ``1``] * power;` `                    ``g[i][p] = Math.max(g[i][p], newOption);` `                    ``power *= primes.get(p - ``1``);` `                ``}` `            ``}` `        ``}` `        ``System.out.println(g[n][primes.size()]);` `    ``}` `}`

## Python3

 `import` `math` `n ``=` `4` `primes ``=` `[]` `max_prime ``=` `[``0``] ``*` `(``2` `*` `n ``+` `1``)` `for` `i ``in` `range``(``2``, ``2` `*` `n ``+` `1``):` `    ``if` `max_prime[i] ``=``=` `0``:` `        ``max_prime[i] ``=` `i;` `        ``primes.append(i);` `    ``j ``=` `0` `    ``while` `j < ``len``(primes) ``and` `primes[j] <``=` `max_prime[i] ``and` `primes[j] ``*` `i <``=` `2` `*` `n:` `        ``max_prime[primes[j] ``*` `i] ``=` `max_prime[i]` `        ``j ``+``=` `1` `g ``=` `[[``1` `for` `i ``in` `range``(``len``(primes) ``+` `1``)] ``for` `j ``in` `range``(n ``+` `1``)]` `for` `p ``in` `range``(``1``, ``len``(primes) ``+` `1``):` `    ``for` `i ``in` `range``(``0``, n ``+` `1``):` `        ``g[i][p] ``=` `g[i][p ``-` `1``]` `        ``power ``=` `primes[p ``-` `1``]` `        ``while` `power <``=` `i:` `            ``new_option ``=` `g[i ``-` `power][p ``-` `1``] ``*` `power;` `            ``g[i][p] ``=` `max``(g[i][p], new_option);` `            ``power ``*``=` `primes[p ``-` `1``];` `print``(g[n][``len``(primes)])`

## C#

 `// Importing required libraries` `using` `System;` `using` `System.Collections.Generic;`   `// Defining the main class` `class` `MainClass {` `  ``static` `void` `Main()` `  ``{`   `    ``// Initializing the value of n` `    ``int` `n = 4; ``// Declaring and initializing the lists` `    ``List<``int``> primes = ``new` `List<``int``>();` `    ``List<``int``> max_prime = ``new` `List<``int``>();` `    ``for` `(``int` `i = 0; i <= 2 * n; ++i) {` `      ``max_prime.Add(0);` `    ``}`   `    ``// Finding the prime numbers` `    ``for` `(``int` `i = 2; i <= 2 * n; ++i) {` `      ``if` `(max_prime[i] == 0) {` `        ``max_prime[i] = i;` `        ``primes.Add(i);` `      ``}` `      ``for` `(``int` `j = 0; j < primes.Count` `           ``&& primes[j] <= max_prime[i]` `           ``&& 1L * primes[j] * i <= 2 * n;` `           ``++j) {` `        ``max_prime[primes[j] * i] = max_prime[i];` `      ``}` `    ``}`   `    ``// Initializing the 2D list with all values as 1` `    ``List > g = ``new` `List >();` `    ``for` `(``int` `i = 0; i <= n; ++i) {` `      ``List<``long``> row = ``new` `List<``long``>();` `      ``for` `(``int` `j = 0; j <= primes.Count; ++j) {` `        ``row.Add(1L);` `      ``}` `      ``g.Add(row);` `    ``}`   `    ``// Finding the maximum product of primes such that` `    ``// the sum of the primes is n` `    ``for` `(``int` `p = 1; p <= primes.Count; ++p) {` `      ``for` `(``int` `i = 0; i <= n; ++i) {` `        ``g[i][p] = g[i][p - 1];` `        ``long` `power = primes[p - 1];` `        ``while` `(power <= i) {` `          ``long` `new_option` `            ``= g[i - (``int``)power][p - 1] * power;` `          ``g[i][p] = Math.Max(g[i][p], new_option);` `          ``power *= primes[p - 1];` `        ``}` `      ``}` `    ``}`   `    ``// Printing the maximum product of primes such that` `    ``// the sum of the primes is n` `    ``Console.WriteLine(g[n][primes.Count]);` `  ``}` `}`

## Javascript

 `// Import required libraries` `// None needed in JavaScript`   `// Define the main function` `function` `main() {` `    ``const n = 4;` `    ``const primes = [];` `    ``const maxPrime = ``new` `Array(2 * n + 1).fill(0);`   `    ``// Calculate the maximum prime factor for each number between 2 and 2n` `    ``for` `(let i = 2; i <= 2 * n; ++i) {` `        ``if` `(maxPrime[i] === 0) {` `            ``maxPrime[i] = i;` `            ``primes.push(i);` `        ``}` `        ``for` `(let j = 0; j < primes.length && primes[j] <= maxPrime[i] &&` `            ``primes[j] * i <= 2 * n; ++j) {` `            ``maxPrime[primes[j] * i] = maxPrime[i];` `        ``}` `    ``}`   `    ``// Create a 2D array g to store the maximum product for each i and j` `    ``const g = ``new` `Array(n + 1).fill().map(() => ``new` `Array(primes.length + 1).fill(1));`   `    ``// Fill in the g array` `    ``for` `(let p = 1; p <= primes.length; ++p) {` `        ``for` `(let i = 0; i <= n; ++i) {` `            ``g[i][p] = g[i][p - 1];` `            ``let power = primes[p - 1];` `            ``while` `(power <= i) {` `                ``const newOption = g[i - power][p - 1] * power;` `                ``g[i][p] = Math.max(g[i][p], newOption);` `                ``power *= primes[p - 1];` `            ``}` `        ``}` `    ``}`   `    ``// Print the maximum product for n` `    ``console.log(g[n][primes.length]);` `}`   `// Call the main function to run the program` `main();`

Time complexity: O(N^2 / logN)

Proof. We use the fact that there are approx n/logn primes less than n and that log(sqrt(n)) = 1/2 log(n). For primes that are <= sqrt(N), we check no more than log2(N) powers. So the time complexity for these primes is O(N * (sqrtN/0.5log(N)) * logN) = O(N * sqrtN)

For primes that are > sqrt(N), we check exactly one power.  So the time complexity for these primes is O(N * (N/logN – sqrtN / 0.5logN) * 1) = O(N * N / logN) = O(N^2 / logN).

So the time complexity is O(NsqrtN + N^2/logN) = O(N^2/logN). QED

Space complexity: O(N^2 / logN).

It should be noted that for large enough n you can’t use standard integer types to get the answer. Instead, you should use long arithmetic. For multiplying you could use, for example, FFT.

My Personal Notes arrow_drop_up
Related Articles