Open In App

Number of ways to make N using product of M integers

Last Updated : 31 Jul, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given two integers N (1 <= N <= 1e9) and M (M <= 1e5), the task is to find the number of ways to represent the number N in terms of the product of M integers. Find the answer modulo 1e9+7.

Examples:

Input: N = 4, M = 2
Output: 6
Explanation: The number of combinations is as follows resulting in the answer 6:

  • 1 x 4
  • -1 x -4
  • -4 x -1
  • 4 x 1
  • 2 x 2
  • -2 x -2

Input: N = -10, M = 2
Output: 8
Explanation: The combinations are as follows resulting in the answer 8:

  • 1 x -10
  • -10 x 1
  • -1 x 10
  • 10 x -1
  • 2 x -5
  • -5 x 2
  • 5 x -2
  • -2 x 5

Approach: To solve the problem follow the below idea:

From the prime factorization of N determining the M integers (X1, X2, … , Xm) that generate a product of N would be equal to determining the sign for each Xi and determining the number of times a prime number p divides the integer Xi. Now as the problem now translates into choosing the prime numbers from the prime factorisation of N to make group of M we will use combinatorics. Below is the indepth editorial along with the proof of this idea.

In-depth editorial:

  • N can be any integer, negative or positive. Hence let the M integers be (X1, X2, …, Xm) such that ∏Xi = |N|.
  • For each element Xi we can assign two signs, + and/or -. Once we assign the signs to M-1 integers, the sign of the Mth integer is automatically determined. Hence we have 2M-1 choices for sign determination.
  • Let the unique prime factorization of integer Xi be (pjej), where pj represents jth prime with ejth exponent to it. The prime pj divides integer Xi for ej number of times.
  • The integer |N| can be represented as |N| = ∏pjej.
  • Now we need to count the number of ways to distribute e occurrences of p among the M integers (X1, X2, …, Xm).
  • We can solve this using the stars and bars technique. Consider there are e stars that need to be put into M groups. To make M groups, M-1 bars are required. This leads to e stars and M-1 bars.
  • Thus we have to choose e positions out of the total e+M-1 positions. This is equivalent to finding \binom{e+M-1}{e}        which is equal to \\frac{(e + M - 1)!}{e! * (M - 1)!}
  • Thus finally for |N| = ∏pjej the answer will be 2^{M-1}*\prod_{j}{\binom{e_j+M-1}{e_j}}
  • This gives the number of ways to choose M integers, resulting in the product N.

Proof for the above idea:

  • The number N will be made up of some integer products such as (a, b, c) which is of size M.
  • But also using the prime factorization, we can say that |N| = ∏pjej for some j.
  • From point (1) and point (2) we can conclude that the integer set (a, b, c) will also be equal to ∏pje.
  • Now as the integer set can take any positive or negative value depending on the value of N if M such integers are to be produced then we can have 2 sign choices for the M-1 integers and depending on the value of N the choice of the Mth integer will be decided automatically. Hence the factor 2M-1 comes into existence.
  • Using point (3) the integer set of size M will be some combination of pjej that is, the integers from the set will be produced by some set of p raised to some set of exponent e. The below example will help to understand better:
    • Suppose N = 12 the prime factorisation will be 22 x 31.
    • Now the set of primes is p = {2, 3} and the corresponding exponents are e = {2, 1}. But now using the set p and e we can produce different integers whose product corresponds to N
    • 21 x 31 = 6 and 21 x 30 = 2 which is 6 x 2 = 12 = N
  • Now as we just need M of those integers to be produced from the prime factors we have to distribute e occurrence of p among M places. Hence we have to group the e number of p’s into M groups. Using the stars and bars technique we have e stars and M-1 bars and among those M-1 different positions to out of e+M-1 positions. This leads to the formula \prod_{j}{\binom{e_j+M-1}{e_j}}

Below is the implementation for the above approach:

C++

// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
const long long MOD = 1e9 + 7;
 
const long long sz = 3e5;
 
// Function to perform modular
// multiplication
long long modularMultiplication(long long a, long long b)
{
    return ((a % MOD) * (b % MOD)) % MOD;
}
 
// Precomputes the modular inverses
// for numbers from 1 to sz-1
void precomputeInverse(vector<long long>& inv)
{
    long long p = MOD;
    inv[1] = 1;
    for (long long i = 2; i < sz; ++i) {
 
        // Calculate the modular inverse
        // of i using Fermat's Little Theorem
        inv[i] = modularMultiplication(p - (p / i),
                                       inv[p % i]);
    }
}
 
// Precomputes the factorials and their
// modular inverses for numbers from
// 1 to sz-1
void precomputeFactorial(vector<long long>& factorial,
                         vector<long long>& inv_factorial,
                         vector<long long>& inv)
{
    factorial[0] = 1;
    inv_factorial[0] = 1;
    for (long long i = 1; i < sz; i++) {
 
        // Calculate the factorial
        // of i
        factorial[i]
            = modularMultiplication(factorial[i - 1], i);
        // Calculate the modular inverse
        // of the factorial of i
        inv_factorial[i] = modularMultiplication(
            inv_factorial[i - 1], inv[i]);
    }
}
 
// Calculates the binomial coefficient
// C(n, k) using precomputed factorials
// and modular inverses
long long
binomialCoefficient(long long n, long long k,
                    vector<long long>& factorial,
                    vector<long long>& inv_factorial)
{
 
    // Calculate the numerator of the
    // binomial coefficient
    long long res = modularMultiplication(factorial[n],
                                          inv_factorial[k]);
 
    // Calculate the denominator of
    // the binomial coefficient
    res = modularMultiplication(res, inv_factorial[n - k]);
    return res;
}
 
// Calculates the prime factorization of
// N and computes the answer
long long
primeFactorization(long long N, long long M,
                   vector<long long>& factorial,
                   vector<long long>& inv_factorial)
{
    long long ans = 1;
    for (long long p = 2; p * p <= N; p++) {
 
        // Check if p is a prime
        // factor of N
        if (N % p == 0) {
            long long e = 0;
            while (N % p == 0) {
 
                // Divide N by p repeatedly
                // to count the exponent e
                N = N / p;
                e++;
            }
 
            // Calculate the binomial
            // coefficient and multiply
            // it with the answer
            ans = modularMultiplication(
                ans,
                binomialCoefficient(e + M - 1, e, factorial,
                                    inv_factorial));
        }
    }
 
    // Check if N is a prime factor
    // greater than sqrt(N)
    if (N > 1) {
        long long e = 1;
 
        // Calculate the binomial
        // coefficient and multiply
        // it with the answer
        ans = modularMultiplication(
            ans,
            binomialCoefficient(e + M - 1, e, factorial,
                                inv_factorial));
    }
    return ans;
}
 
// Calculates the final answer by
// multiplying the result of
// prime factorization with 2^(M-1)
long long calculate(long long N, long long M,
                    vector<long long>& factorial,
                    vector<long long>& inv_factorial)
{
    long long ans = 1;
    for (long long i = 0; i < M - 1; i++) {
 
        // Multiply ans by 2 M-1 times
        ans = modularMultiplication(ans, 2);
    }
 
    // Multiply ans by the result of
    // prime factorization
    ans = modularMultiplication(
        ans,
        primeFactorization(N, M, factorial, inv_factorial));
    return ans;
}
 
// Solves the problem by handling input,
// calling necessary functions, and
// returning the final result
long long solve(long long N, long long M)
{
    if (N < 0) {
 
        // Take the absolute value of
        // N if it is negative
        N = -N;
    }
 
    vector<long long> factorial(sz), inv(sz),
        inv_factorial(sz);
 
    // Precompute modular inverses
    precomputeInverse(inv);
 
    // Precompute factorials and
    // their modular inverses
    precomputeFactorial(factorial, inv_factorial, inv);
 
    // Calculate the final answer
    long long ans
        = calculate(N, M, factorial, inv_factorial);
 
    return ans;
}
 
// Drivers code
int main()
{
    long long N, M;
    N = 4;
    M = 2;
 
    // Call the solve function and
    // print the result
    cout << "Number of ways to represent N using M "
            "integers is: "
         << solve(N, M) << ".\n";
 
    return 0;
}

                    

Java

import java.util.*;
 
public class Main {
    static final long MOD = (long)1e9 + 7;
    static final long sz = (long)3e5;
 
    // Function to perform modular multiplication
    static long modularMultiplication(long a, long b)
    {
        return ((a % MOD) * (b % MOD)) % MOD;
    }
 
    // Precomputes the modular inverses for numbers from 1
    // to sz-1
    static void precomputeInverse(ArrayList<Long> inv)
    {
        long p = MOD;
        inv.set(1, 1L);
        for (long i = 2; i < sz; ++i) {
            // Calculate the modular inverse of i using
            // Fermat's Little Theorem
            inv.set((int)i, modularMultiplication(
                                p - (p / i),
                                inv.get((int)(p % i))));
        }
    }
 
    // Precomputes the factorials and their modular inverses
    // for numbers from 1 to sz-1
    static void
    precomputeFactorial(ArrayList<Long> factorial,
                        ArrayList<Long> inv_factorial,
                        ArrayList<Long> inv)
    {
        factorial.set(0, 1L);
        inv_factorial.set(0, 1L);
        for (long i = 1; i < sz; i++) {
            // Calculate the factorial of i
            factorial.set(
                (int)i,
                modularMultiplication(
                    factorial.get((int)(i - 1)), i));
            // Calculate the modular inverse of the
            // factorial of i
            inv_factorial.set(
                (int)i, modularMultiplication(
                            inv_factorial.get((int)(i - 1)),
                            inv.get((int)i)));
        }
    }
 
    // Calculates the binomial coefficient C(n, k) using
    // precomputed factorials and modular inverses
    static long
    binomialCoefficient(long n, long k,
                        ArrayList<Long> factorial,
                        ArrayList<Long> inv_factorial)
    {
        // Calculate the numerator of the binomial
        // coefficient
        long res = modularMultiplication(
            factorial.get((int)n),
            inv_factorial.get((int)k));
        // Calculate the denominator of the binomial
        // coefficient
        res = modularMultiplication(
            res, inv_factorial.get((int)(n - k)));
        return res;
    }
 
    // Calculates the prime factorization of N and computes
    // the answer
    static long
    primeFactorization(long N, long M,
                       ArrayList<Long> factorial,
                       ArrayList<Long> inv_factorial)
    {
        long ans = 1;
        for (long p = 2; p * p <= N; p++) {
            // Check if p is a prime factor of N
            if (N % p == 0) {
                long e = 0;
                while (N % p == 0) {
                    // Divide N by p repeatedly to count the
                    // exponent e
                    N = N / p;
                    e++;
                }
                // Calculate the binomial coefficient and
                // multiply it with the answer
                ans = modularMultiplication(
                    ans, binomialCoefficient(
                             e + M - 1, e, factorial,
                             inv_factorial));
            }
        }
        // Check if N is a prime factor greater than sqrt(N)
        if (N > 1) {
            long e = 1;
            // Calculate the binomial coefficient and
            // multiply it with the answer
            ans = modularMultiplication(
                ans,
                binomialCoefficient(e + M - 1, e, factorial,
                                    inv_factorial));
        }
        return ans;
    }
 
    // Calculates the final answer by multiplying the result
    // of prime factorization with 2^(M-1)
    static long calculate(long N, long M,
                          ArrayList<Long> factorial,
                          ArrayList<Long> inv_factorial)
    {
        long ans = 1;
        for (long i = 0; i < M - 1; i++) {
            // Multiply ans by 2 M-1 times
            ans = modularMultiplication(ans, 2);
        }
        // Multiply ans by the result of prime factorization
        ans = modularMultiplication(
            ans, primeFactorization(N, M, factorial,
                                    inv_factorial));
        return ans;
    }
 
    // Solves the problem by handling input, calling
    // necessary functions, and returning the final result
    static long solve(long N, long M)
    {
        if (N < 0) {
            // Take the absolute value of N if it is
            // negative
            N = -N;
        }
 
        ArrayList<Long> factorial = new ArrayList<>();
        ArrayList<Long> inv = new ArrayList<>();
        ArrayList<Long> inv_factorial = new ArrayList<>();
 
        for (int i = 0; i < sz; i++) {
            factorial.add(0L);
            inv.add(0L);
            inv_factorial.add(0L);
        }
 
        // Precompute modular inverses
        precomputeInverse(inv);
        // Precompute factorials and their modular inverses
        precomputeFactorial(factorial, inv_factorial, inv);
 
        // Calculate the final answer
        long ans
            = calculate(N, M, factorial, inv_factorial);
 
        return ans;
    }
 
    public static void main(String[] args)
    {
        long N, M;
        N = 4;
        M = 2;
 
        // Call the solve function and print the result
        System.out.println(
            "Number of ways to represent N using M integers is: "
            + solve(N, M) + ".");
    }
}

                    

Python3

MOD = int(1e9 + 7)
sz = int(3e5)
 
# Function to perform modular multiplication
 
 
def modularMultiplication(a, b):
    return ((a % MOD) * (b % MOD)) % MOD
 
# Precomputes the modular inverses for numbers from 1 to sz-1
 
 
def precomputeInverse(inv):
    p = MOD
    inv[1] = 1
    for i in range(2, sz):
        # Calculate the modular inverse of i using Fermat's Little Theorem
        inv[i] = modularMultiplication(p - (p // i), inv[p % i])
 
# Precomputes the factorials and their modular inverses for numbers from 1 to sz-1
 
 
def precomputeFactorial(factorial, inv_factorial, inv):
    factorial[0] = 1
    inv_factorial[0] = 1
    for i in range(1, sz):
        # Calculate the factorial of i
        factorial[i] = modularMultiplication(factorial[i - 1], i)
        # Calculate the modular inverse of the factorial of i
        inv_factorial[i] = modularMultiplication(inv_factorial[i - 1], inv[i])
 
# Calculates the binomial coefficient C(n, k) using precomputed factorials and modular inverses
 
 
def binomialCoefficient(n, k, factorial, inv_factorial):
    # Calculate the numerator of the binomial coefficient
    res = modularMultiplication(factorial[n], inv_factorial[k])
    # Calculate the denominator of the binomial coefficient
    res = modularMultiplication(res, inv_factorial[n - k])
    return res
 
# Calculates the prime factorization of N and computes the answer
 
 
def primeFactorization(N, M, factorial, inv_factorial):
    ans = 1
    p = 2
    while p * p <= N:
        # Check if p is a prime factor of N
        if N % p == 0:
            e = 0
            while N % p == 0:
                # Divide N by p repeatedly to count the exponent e
                N //= p
                e += 1
            # Calculate the binomial coefficient and multiply it with the answer
            ans = modularMultiplication(ans, binomialCoefficient(
                e + M - 1, e, factorial, inv_factorial))
        p += 1
    # Check if N is a prime factor greater than sqrt(N)
    if N > 1:
        e = 1
        # Calculate the binomial coefficient and multiply it with the answer
        ans = modularMultiplication(ans, binomialCoefficient(
            e + M - 1, e, factorial, inv_factorial))
    return ans
 
# Calculates the final answer by multiplying the result of prime factorization with 2^(M-1)
 
 
def calculate(N, M, factorial, inv_factorial):
    ans = 1
    for i in range(M - 1):
        # Multiply ans by 2 M-1 times
        ans = modularMultiplication(ans, 2)
    # Multiply ans by the result of prime factorization
    ans = modularMultiplication(
        ans, primeFactorization(N, M, factorial, inv_factorial))
    return ans
 
# Solves the problem by handling input, calling necessary functions, and returning the final result
 
 
def solve(N, M):
    if N < 0:
        # Take the absolute value of N if it is negative
        N = abs(N)
 
    factorial = [0] * sz
    inv = [0] * sz
    inv_factorial = [0] * sz
 
    # Precompute modular inverses
    precomputeInverse(inv)
    # Precompute factorials and their modular inverses
    precomputeFactorial(factorial, inv_factorial, inv)
 
    # Calculate the final answer
    ans = calculate(N, M, factorial, inv_factorial)
 
    return ans
 
 
# Main program
if __name__ == '__main__':
    N = 4
    M = 2
 
    # Call the solve function and print the result
    print("Number of ways to represent N using M integers is:", solve(N, M), ".")

                    

C#

using System;
using System.Collections.Generic;
 
class Program {
    const long MOD = 1000000007;
    const long sz = 300000;
 
    // Function to perform modular multiplication
    static long ModularMultiplication(long a, long b)
    {
        return ((a % MOD) * (b % MOD)) % MOD;
    }
 
    // Precomputes the modular inverses for numbers from 1
    // to sz-1
    static void PrecomputeInverse(List<long> inv)
    {
        long p = MOD;
        inv[1] = 1;
        for (long i = 2; i < sz; ++i) {
            // Calculate the modular inverse of i using
            // Fermat's Little Theorem
            inv[(int)i] = ModularMultiplication(
                p - (p / i), inv[(int)(p % i)]);
        }
    }
 
    // Precomputes the factorials and their modular inverses
    // for numbers from 1 to sz-1
    static void
    PrecomputeFactorial(List<long> factorial,
                        List<long> inv_factorial,
                        List<long> inv)
    {
        factorial[0] = 1;
        inv_factorial[0] = 1;
        for (long i = 1; i < sz; i++) {
            // Calculate the factorial of i
            factorial[(int)i] = ModularMultiplication(
                factorial[(int)(i - 1)], i);
            // Calculate the modular inverse of the
            // factorial of i
            inv_factorial[(int)i] = ModularMultiplication(
                inv_factorial[(int)(i - 1)], inv[(int)i]);
        }
    }
 
    // Calculates the binomial coefficient C(n, k) using
    // precomputed factorials and modular inverses
    static long
    BinomialCoefficient(long n, long k,
                        List<long> factorial,
                        List<long> inv_factorial)
    {
        // Calculate the numerator of the binomial
        // coefficient
        long res = ModularMultiplication(
            factorial[(int)n], inv_factorial[(int)k]);
        // Calculate the denominator of the binomial
        // coefficient
        res = ModularMultiplication(
            res, inv_factorial[(int)(n - k)]);
        return res;
    }
 
    // Calculates the prime factorization of N and computes
    // the answer
    static long PrimeFactorization(long N, long M,
                                   List<long> factorial,
                                   List<long> inv_factorial)
    {
        long ans = 1;
        for (long p = 2; p * p <= N; p++) {
            // Check if p is a prime factor of N
            if (N % p == 0) {
                long e = 0;
                while (N % p == 0) {
                    // Divide N by p repeatedly to count the
                    // exponent e
                    N = N / p;
                    e++;
                }
                // Calculate the binomial coefficient and
                // multiply it with the answer
                ans = ModularMultiplication(
                    ans, BinomialCoefficient(
                             e + M - 1, e, factorial,
                             inv_factorial));
            }
        }
        // Check if N is a prime factor greater than sqrt(N)
        if (N > 1) {
            long e = 1;
            // Calculate the binomial coefficient and
            // multiply it with the answer
            ans = ModularMultiplication(
                ans,
                BinomialCoefficient(e + M - 1, e, factorial,
                                    inv_factorial));
        }
        return ans;
    }
 
    // Calculates the final answer by multiplying the result
    // of prime factorization with 2^(M-1)
    static long Calculate(long N, long M,
                          List<long> factorial,
                          List<long> inv_factorial)
    {
        long ans = 1;
        for (long i = 0; i < M - 1; i++) {
            // Multiply ans by 2 M-1 times
            ans = ModularMultiplication(ans, 2);
        }
        // Multiply ans by the result of prime factorization
        ans = ModularMultiplication(
            ans, PrimeFactorization(N, M, factorial,
                                    inv_factorial));
        return ans;
    }
 
    // Solves the problem by handling input, calling
    // necessary functions, and returning the final result
    static long Solve(long N, long M)
    {
        if (N < 0) {
            // Take the absolute value of N if it is
            // negative
            N = -N;
        }
 
        List<long> factorial = new List<long>(new long[sz]);
        List<long> inv = new List<long>(new long[sz]);
        List<long> inv_factorial
            = new List<long>(new long[sz]);
 
        // Precompute modular inverses
        PrecomputeInverse(inv);
        // Precompute factorials and their modular inverses
        PrecomputeFactorial(factorial, inv_factorial, inv);
 
        // Calculate the final answer
        long ans
            = Calculate(N, M, factorial, inv_factorial);
 
        return ans;
    }
 
    static void Main()
    {
        long N, M;
        N = 4;
        M = 2;
 
        // Call the Solve function and print the result
        Console.WriteLine(
            "Number of ways to represent N using M integers is: "
            + Solve(N, M) + ".");
    }
}

                    

Javascript

const MOD = 1e9 + 7;
const sz = 3e5;
 
// Function to perform modular multiplication
function modularMultiplication(a, b) {
    return ((a % MOD) * (b % MOD)) % MOD;
}
 
// Precomputes the modular inverses for numbers from 1 to sz-1
function precomputeInverse(inv) {
    const p = MOD;
    inv[1] = 1;
    for (let i = 2; i < sz; ++i) {
        // Calculate the modular inverse of i using Fermat's Little Theorem
        inv[i] = modularMultiplication(p - Math.floor(p / i), inv[p % i]);
    }
}
 
// Precomputes the factorials and their modular inverses for numbers from 1 to sz-1
function precomputeFactorial(factorial, inv_factorial, inv) {
    factorial[0] = 1;
    inv_factorial[0] = 1;
    for (let i = 1; i < sz; i++) {
        // Calculate the factorial of i
        factorial[i] = modularMultiplication(factorial[i - 1], i);
        // Calculate the modular inverse of the factorial of i
        inv_factorial[i] = modularMultiplication(inv_factorial[i - 1], inv[i]);
    }
}
 
// Calculates the binomial coefficient C(n, k) using precomputed factorials and modular inverses
function binomialCoefficient(n, k, factorial, inv_factorial) {
    // Calculate the numerator of the binomial coefficient
    let res = modularMultiplication(factorial[n], inv_factorial[k]);
    // Calculate the denominator of the binomial coefficient
    res = modularMultiplication(res, inv_factorial[n - k]);
    return res;
}
 
// Calculates the prime factorization of N and computes the answer
function primeFactorization(N, M, factorial, inv_factorial) {
    let ans = 1;
    for (let p = 2; p * p <= N; p++) {
        // Check if p is a prime factor of N
        if (N % p === 0) {
            let e = 0;
            while (N % p === 0) {
                // Divide N by p repeatedly to count the exponent e
                N = Math.floor(N / p);
                e++;
            }
            // Calculate the binomial coefficient and multiply it with the answer
            ans = modularMultiplication(ans, binomialCoefficient(e + M - 1, e, factorial, inv_factorial));
        }
    }
    // Check if N is a prime factor greater than sqrt(N)
    if (N > 1) {
        let e = 1;
        // Calculate the binomial coefficient and multiply it with the answer
        ans = modularMultiplication(ans, binomialCoefficient(e + M - 1, e, factorial, inv_factorial));
    }
    return ans;
}
 
// Calculates the final answer by multiplying the result of prime factorization with 2^(M-1)
function calculate(N, M, factorial, inv_factorial) {
    let ans = 1;
    for (let i = 0; i < M - 1; i++) {
        // Multiply ans by 2 M-1 times
        ans = modularMultiplication(ans, 2);
    }
    // Multiply ans by the result of prime factorization
    ans = modularMultiplication(ans, primeFactorization(N, M, factorial, inv_factorial));
    return ans;
}
 
// Solves the problem by handling input, calling necessary functions, and returning the final result
function solve(N, M) {
    if (N < 0) {
        // Take the absolute value of N if it is negative
        N = Math.abs(N);
    }
 
    const factorial = new Array(sz).fill(0);
    const inv = new Array(sz).fill(0);
    const inv_factorial = new Array(sz).fill(0);
 
    // Precompute modular inverses
    precomputeInverse(inv);
    // Precompute factorials and their modular inverses
    precomputeFactorial(factorial, inv_factorial, inv);
 
    // Calculate the final answer
    const ans = calculate(N, M, factorial, inv_factorial);
 
    return ans;
}
 
// Main program
const N = 4;
const M = 2;
 
// Call the solve function and print the result
console.log("Number of ways to represent N using M integers is: " + solve(N, M) + ".");

                    

Output
Number of ways to represent N using M integers is: 6.

Time Complexity: O(SqrtN + M) = O(M);
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads