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++ 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;
}
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) + ".");
}
}
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), ".")
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) + ".");
}
}
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)