Count of distinct numbers formed by shuffling the digits of a large number N

Given a large number N in the form of a string, the task is to determine the count of distinct numbers that can be formed by shuffling the digits of number N.

Note: 

  • N may contain leading zeros. 
  • The number itself is also taken into count.
  • Since the answer could be very large, print result modulo 109+7.

Examples:

Input: N = “23”
Output: 2
Explanation:
23 can be shuffled as {23, 32}

Input: N = “0223”
Output: 12
Explanation:
0223 can be shuffled as {2230, 2203, 2023, 3220, 3202, 3022, 2320, 2302, 2032, 0232, 0322, 0223 }

 

Naive Approach: The naive idea is to find all the permutations of the given number and print the count of unique numbers generated. But since the given number N is very large, it cannot be used.



Time Complexity: O(N * N!)
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach, the idea is to use the concept of Permutation and Combination and Fermat’s little theorem. Below are the steps:

  1. Use Fermat’s Little Theorem to find Modulo Multiplicative Inverse under modulo M where M is 109+7.
  2. Instead of finding all the permutations, the result will be factorial of the length of given number N divided by the product of factorial of the count of a number as:

    count = \frac{K!}{C[i]!}

    where, 
    K is the number of digits in N
    C[i] is the count of digits(from 0 to 9) in N.

  3. Create an array of in which at each index store the factorial of that index.
  4. In order to store the count of each digit, create an array of size 10 and initialize it with 0.
  5. Initialize a variable answer with a value factorial of the length of N. For each count of a digit, find it’s a modular multiplicative inverse under modulo m and multiple with the result as:

    Since the count is 

    count = \frac{K!}{\sum_{i = 0}^{9}{C[i]!}}

    According to fermat little theorm: 

    x^{-1} mod M = x^{M - 2} mod M

    Therefore the count is given by: 

    count = ((K!)* ( \sum_{i = 0}^{9}(factorial[i]^{m - 2})mod M) mod M)

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
  
// Recursive function to return the value
// of (x ^ n) % m
ll modexp(ll x, ll n, ll m)
{
    // Base Case
    if (n == 0) {
        return 1;
    }
  
    // If N is even
    else if (n % 2 == 0) {
        return modexp((x * x) % m,
                      n / 2, m);
    }
  
    // Else N is odd
    else {
        return (x * modexp((x * x) % m,
                           (n - 1) / 2, m)
                % m);
    }
}
  
// Function to find modular inverse
// of a number x under modulo m
ll modInverse(ll x, ll m)
{
    // Using Fermat's little theorem
    return modexp(x, m - 2, m);
}
  
// Function to count of numbers formed by
// shuffling the digits of a large number N
void countNumbers(string N)
{
    // Modulo value
    ll m = 1000000007;
  
    // Array to store the factorials
    // upto the maximum value of N
    ll factorial[100001];
  
    // Store factorial of i at index i
    factorial[0] = 1;
    for (ll i = 1; i < 100001; i++) {
  
        factorial[i] = (factorial[i - 1] * i) % m;
    }
  
    // To store count of occurrence
    // of a digit
    ll count[10];
  
    for (ll i = 0; i < 10; i++) {
        count[i] = 0;
    }
  
    ll length = N.length();
  
    for (ll i = 0; i < length; i++)
  
        // Increment the count of
        // digit occured
        count[N[i] - '0']++;
  
    // Assign the factorial of
    // length of input
    ll result = factorial[length];
  
    // Multiplying result with the
    // modulo multiplicative inverse of
    // factorial of count of i
    for (ll i = 0; i < 10; i++) {
  
        result = (result
                  * modInverse(factorial[count[i]], m))
                 % m;
    }
  
    // Print the result
    cout << result;
}
  
// Driver Code
int main()
{
    // Given Number as string
    string N = "0223";
  
    // Function call
    countNumbers(N);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach 
import java.util.*; 
  
class GFG{
      
// Recursive function to return the value 
// of (x ^ n) % m 
static long modexp(long x, long n, long m) 
      
    // Base Case 
    if (n == 0
    
        return 1
    
  
    // If N is even 
    else if (n % 2 == 0)
    
        return modexp((x * x) % m, 
                       n / 2, m); 
    
  
    // Else N is odd 
    else
    
        return (x * modexp((x * x) % m, 
                   (n - 1) / 2, m) % m); 
    
  
// Function to find modular inverse 
// of a number x under modulo m 
static long modInverse(long x, long m) 
      
    // Using Fermat's little theorem 
    return modexp(x, m - 2, m); 
  
// Function to count of numbers formed by 
// shuffling the digits of a large number N 
static void countNumbers(String N) 
      
    // Modulo value 
    long m = 1000000007
  
    // Array to store the factorials 
    // upto the maximum value of N 
    long factorial[] = new long [100001]; 
  
    // Store factorial of i at index i 
    factorial[0] = 1
    for(int i = 1; i < 100001; i++)
    
        factorial[i] = (factorial[i - 1] * i) % m; 
    
  
    // To store count of occurrence 
    // of a digit 
    long count[] = new long [10]; 
  
    for(int i = 0; i < 10; i++) 
    
        count[i] = 0
    
  
    long length = N.length(); 
  
    for(int i = 0; i < length; i++) 
      
        // Increment the count of 
        // digit occured 
        count[N.charAt(i) - '0']++; 
  
    // Assign the factorial of 
    // length of input 
    long result = factorial[(int)length]; 
  
    // Multiplying result with the 
    // modulo multiplicative inverse of 
    // factorial of count of i 
    for(int i = 0; i < 10; i++)
    
        result = (result * 
                  modInverse(
                      factorial[(int)count[i]], m)) % m; 
    
  
    // Print the result 
    System.out.println(result);
  
// Driver code
public static void main(String args[]) 
{
      
    // Given number as string 
    String N = "0223"
  
    // Function call
    countNumbers(N);
}
}
  
// This code is contributed by Stream_Cipher

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach 
  
# Recursive function to return the value 
# of (x ^ n) % m 
def modexp(x, n, m):
      
    # Base Case 
    if (n == 0):
        return 1
      
    # If N is even 
    else:
        if (n % 2 == 0): 
            return modexp((x * x) % m,
                           n / 2, m); 
      
        # Else N is odd 
        else:
            return (x * modexp((x * x) % m,
                       (n - 1) / 2, m) % m)
  
# Function to find modular inverse 
# of a number x under modulo m 
def modInverse(x, m):
      
    # Using Fermat's little theorem 
    return modexp(x, m - 2, m)
  
# Function to count of numbers formed by 
# shuffling the digits of a large number N 
def countNumbers(N): 
      
    # Modulo value 
    m = 1000000007
      
    # Array to store the factorials 
    # upto the maximum value of N 
    factorial = [0 for x in range(100001)]
      
    # Store factorial of i at index i 
    factorial[0] = 1
      
    for i in range(1, 100001): 
        factorial[i] = (factorial[i - 1] * i) % m
      
    # To store count of occurrence 
    # of a digit 
    count = [0 for x in range(10)]
      
    for i in range(0, 10):
        count[i] = 0
          
    length = len(N) 
      
    for i in range(0, length):
      
        # Increment the count of 
        # digit occured 
        count[int(N[i])] += 1
      
    # Assign the factorial of 
    # length of input 
    result = factorial[int(length)]
      
    # Multiplying result with the 
    # modulo multiplicative inverse of 
    # factorial of count of i 
    for i in range(0, 10):
        result = (result * 
                  modInverse(
                      factorial[int(count[i])], m)) % m
      
    # Print the result 
    print(result)
  
# Driver code
  
# Given number as string 
N = "0223"
  
# Function call
countNumbers(N)
  
# This code is contributed by Stream_Cipher

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for the above approach 
using System.Collections.Generic; 
using System;
  
class GFG{
      
// Recursive function to return the value 
// of (x ^ n) % m 
static long modexp(long x, long n, long m) 
      
    // Base Case 
    if (n == 0)
    
        return 1; 
    
  
    // If N is even 
    else if (n % 2 == 0)
    
        return modexp((x * x) % m, 
                       n / 2, m); 
    
  
    // Else N is odd 
    else 
    
        return (x * modexp((x * x) % m, 
                   (n - 1) / 2, m) % m); 
    
  
// Function to find modular inverse 
// of a number x under modulo m 
static long modInverse(long x, long m) 
      
    // Using Fermat's little theorem 
    return modexp(x, m - 2, m); 
  
// Function to count of numbers formed by 
// shuffling the digits of a large number N 
static void countNumbers(string N) 
      
    // Modulo value 
    long m = 1000000007; 
  
    // Array to store the factorials 
    // upto the maximum value of N 
    long []factorial = new long [100001]; 
  
    // Store factorial of i at index i 
    factorial[0] = 1; 
    for(int i = 1; i < 100001; i++) 
    
        factorial[i] = (factorial[i - 1] * i) % m; 
    
  
    // To store count of occurrence 
    // of a digit 
    long []count = new long [10]; 
  
    for(int i = 0; i < 10; i++)
    
        count[i] = 0; 
    
  
    long length = N.Length; 
  
    for(int i = 0; i < length; i++) 
  
        // Increment the count of 
        // digit occured 
        count[N[i] - '0']++; 
  
    // Assign the factorial of 
    // length of input 
    long result = factorial[(int)length]; 
  
    // Multiplying result with the 
    // modulo multiplicative inverse of 
    // factorial of count of i 
    for(int i = 0; i < 10; i++)
    
        result = (result * 
                  modInverse(
                      factorial[(int)count[i]], m)) % m; 
    
      
    // Print the result 
    Console.WriteLine(result);
  
// Driver code
public static void Main() 
{
      
    // Given number as string 
    string N = "0223"
  
    // Function call
    countNumbers(N);
}
}
  
// This code is contributed by Stream_Cipher

chevron_right


Output: 

12

Time Complexity: O(K + log(M)). O(K) is used to calculate the factorial of the number N and according to Fermat’s Little Theorem, it takes O(log(M)) to calculate the modulo multiplicative inverse of any number x under modulo m.
Auxiliary Space: O(log10N), where N is the given number N.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : Stream_Cipher