Given the number N which represents the number of students, the task is to calculate all possible ways to rank them according to their CGPA/marks, considering that two or more students can have the same rank. Since the answer can be large, perform the modulo with 109 + 7.
Examples:
Input: N = 1
Output: 1
Explanation:
There is only one way to rank a student, irrespective of his marks.Input: N = 2
Output: 3
Explanation:
First way : if A and B student Got same marks, then Let say A has got higher rank than B .
Second Way : if A and B student Got same marks, then Let say B has got higher rank than A .
Third way: If both got different, Then the person got higher mark , will get higher rank.
Approach: The idea for this problem is to use the Bell Numbers.
- A bell number is a number that counts the possible partitions of a set. Therefore, an N-th bell number is a number of non-empty subsets a set of size N can be partitioned into.
- For example, let’s consider the set {1, 2, 3} for N = 3. The bell number corresponding to N = 3 is 5. This signifies that the given set can be partitioned into the following 5 non-empty subsets:
{{1}, {2}, {3}} {{1, 2}, {3}} {{1, 3}, {2}} {{2, 3}, {1}} {{1, 2, 3}}
- Clearly, the above bell numbers signify all the possible ranks. However, they do not calculate the permutations of the subset.
- Therefore, by multiplying every subset with K!, where K denotes the size of the respective subset, we get all the possible arrangements.
- As the same subproblems can be repeated, we can store the values of each subproblem in a data structure to optimize the complexity.
Implementation:
// C++ program to calculate the number // of ways to give ranks for N // students such that same ranks // are possible #include <bits/stdc++.h> using namespace std;
const int mod = 1e9 + 7;
// Initializing a table in order to // store the bell triangle vector<vector< int > > dp;
// Function to calculate the K-th // bell number int f( int n, int k)
{ // If we have already calculated
// the bell numbers until the
// required N
if (n < k)
return 0;
// Base case
if (n == k)
return 1;
// First Bell Number
if (k == 1)
return 1;
// If the value of the bell
// triangle has already been
// calculated
if (dp[n][k] != -1)
return dp[n][k];
// Fill the defined dp table
return dp[n][k] = ((k * f(n - 1, k)) % mod
+ (f(n - 1, k - 1)) % mod)
% mod;
} // Function to return the number // of ways to give ranks for N // students such that same ranks // are possible long operation( int n)
{ // Resizing the dp table for the
// given value of n
dp.resize(n + 1, vector< int >(n + 1, -1));
// Variables to store the answer
// and the factorial value
long ans = 0, fac = 1;
// Iterating till N
for ( int k = 1; k <= n; k++) {
// Simultaneously calculate the k!
fac *= k;
// Computing the K-th bell number
// and multiplying it with K!
ans = (ans + (fac * f(n, k)) % mod)
% mod;
}
return ans;
} // Driver code int main()
{ int n = 5;
cout << operation(n) << endl;
return 0;
} |
// Java program to calculate the number // of ways to give ranks for N // students such that same ranks // are possible import java.util.*;
class GFG{
static int mod = ( int )(1e9 + 7 );
// Initializing a table in order to // store the bell triangle static int [][]dp;
// Function to calculate the K-th // bell number static int f( int n, int k)
{ // If we have already calculated
// the bell numbers until the
// required N
if (n < k)
return 0 ;
// Base case
if (n == k)
return 1 ;
// First Bell Number
if (k == 1 )
return 1 ;
// If the value of the bell
// triangle has already been
// calculated
if (dp[n][k] != - 1 )
return dp[n][k];
// Fill the defined dp table
return dp[n][k] = ((k * f(n - 1 , k)) % mod +
(f(n - 1 , k - 1 )) % mod) % mod;
} // Function to return the number // of ways to give ranks for N // students such that same ranks // are possible static long operation( int n)
{ // Resizing the dp table for the
// given value of n
dp = new int [n + 1 ][n + 1 ];
for ( int i = 0 ; i < n + 1 ; i++)
{
for ( int j = 0 ; j < n + 1 ; j++)
{
dp[i][j] = - 1 ;
}
}
// Variables to store the answer
// and the factorial value
long ans = 0 , fac = 1 ;
// Iterating till N
for ( int k = 1 ; k <= n; k++)
{
// Simultaneously calculate the k!
fac *= k;
// Computing the K-th bell number
// and multiplying it with K!
ans = (ans + (fac * f(n, k)) % mod) % mod;
}
return ans;
} // Driver code public static void main(String[] args)
{ int n = 5 ;
System.out.print(operation(n) + "\n" );
} } // This code is contributed by amal kumar choubey |
# Python3 program to calculate the number # of ways to give ranks for N # students such that same ranks # are possible mod = 1e9 + 7
# Initializing a table in order to # store the bell triangle dp = [[ - 1 for x in range ( 6 )]
for y in range ( 6 )]
# Function to calculate the K-th # bell number def f(n, k):
# If we have already calculated
# the bell numbers until the
# required N
if (n < k):
return 0
# Base case
if (n = = k):
return 1
# First Bell Number
if (k = = 1 ):
return 1
# If the value of the bell
# triangle has already been
# calculated
if (dp[n][k] ! = - 1 ):
return dp[n][k]
# Fill the defined dp table
dp[n][k] = ((((k * f(n - 1 , k)) % mod +
(f(n - 1 , k - 1 )) % mod) % mod))
return dp[n][k]
# Function to return the number # of ways to give ranks for N # students such that same ranks # are possible def operation(n):
# Resizing the dp table for the
# given value of n
global dp
# Variables to store the answer
# and the factorial value
ans = 0
fac = 1
# Iterating till N
for k in range ( 1 , n + 1 ):
# Simultaneously calculate the k!
fac * = k
# Computing the K-th bell number
# and multiplying it with K!
ans = (ans + (fac * f(n, k)) % mod) % mod
return ans
# Driver code if __name__ = = "__main__" :
n = 5
print ( int (operation(n)))
# This code is contributed by ukasp |
// C# program to calculate the number // of ways to give ranks for N // students such that same ranks // are possible using System;
class GFG{
static int mod = ( int )(1e9 + 7);
// Initializing a table in order to // store the bell triangle static int [,]dp;
// Function to calculate the K-th // bell number static int f( int n, int k)
{ // If we have already calculated
// the bell numbers until the
// required N
if (n < k)
return 0;
// Base case
if (n == k)
return 1;
// First Bell Number
if (k == 1)
return 1;
// If the value of the bell
// triangle has already been
// calculated
if (dp[n, k] != -1)
return dp[n, k];
// Fill the defined dp table
return dp[n, k] = ((k * f(n - 1, k)) % mod +
(f(n - 1, k - 1)) % mod) % mod;
} // Function to return the number // of ways to give ranks for N // students such that same ranks // are possible static long operation( int n)
{ // Resizing the dp table for the
// given value of n
dp = new int [n + 1, n + 1];
for ( int i = 0; i < n + 1; i++)
{
for ( int j = 0; j < n + 1; j++)
{
dp[i, j] = -1;
}
}
// Variables to store the answer
// and the factorial value
long ans = 0, fac = 1;
// Iterating till N
for ( int k = 1; k <= n; k++)
{
// Simultaneously calculate the k!
fac *= k;
// Computing the K-th bell number
// and multiplying it with K!
ans = (ans + (fac * f(n, k)) % mod) % mod;
}
return ans;
} // Driver code public static void Main(String[] args)
{ int n = 5;
Console.Write(operation(n) + "\n" );
} } // This code is contributed by amal kumar choubey |
<script> // Javascript program to calculate the number // of ways to give ranks for N // students such that same ranks // are possible var mod = parseInt( 1e9 + 7);
// Initializing a table in order to
// store the bell triangle
var dp;
// Function to calculate the K-th
// bell number
function f(n , k) {
// If we have already calculated
// the bell numbers until the
// required N
if (n < k)
return 0;
// Base case
if (n == k)
return 1;
// First Bell Number
if (k == 1)
return 1;
// If the value of the bell
// triangle has already been
// calculated
if (dp[n][k] != -1)
return dp[n][k];
// Fill the defined dp table
return dp[n][k] = ((k * f(n - 1, k)) % mod +
(f(n - 1, k - 1)) % mod) % mod;
}
// Function to return the number
// of ways to give ranks for N
// students such that same ranks
// are possible
function operation(n) {
// Resizing the dp table for the
// given value of n
dp = Array(n + 1).fill().map(()
=>Array(n + 1).fill(0));
for (i = 0; i < n + 1; i++) {
for (j = 0; j < n + 1; j++) {
dp[i][j] = -1;
}
}
// Variables to store the answer
// and the factorial value
var ans = 0, fac = 1;
// Iterating till N
for (k = 1; k <= n; k++) {
// Simultaneously calculate the k!
fac *= k;
// Computing the K-th bell number
// and multiplying it with K!
ans = (ans + (fac * f(n, k)) % mod) % mod;
}
return ans;
}
// Driver code
var n = 5;
document.write(operation(n) + "\n" );
// This code contributed by umadevi9616 </script> |
541
Time Complexity: O(N*N)
Auxiliary Space: O(N*N)
Efficient approach: Using DP Tabulation method ( Iterative approach )
The approach to solving this problem is the same but DP tabulation(bottom-up) method is better the Dp + memorization(top-down) because memorization method needs extra stack space of recursion calls.
Steps to solve this problem:
- Create a vector to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively.
- Return the final solution
Implementation:
#include <bits/stdc++.h> using namespace std;
const int mod = 1e9 + 7;
int operation( int n)
{ vector<vector< int > > dp(n + 1, vector< int >(n + 1));
// Initialize base cases
for ( int i = 0; i <= n; i++) {
dp[i][0] = 0;
dp[i][i] = 1;
}
// Fill the DP table in a bottom-up manner
for ( int i = 1; i <= n; i++) {
for ( int j = 1; j < i; j++) {
dp[i][j] = (j * dp[i - 1][j] + dp[i - 1][j - 1])
% mod;
}
dp[i][i] = 1;
}
// Calculate the answer using the DP table
long ans = 0, fac = 1;
for ( int k = 1; k <= n; k++) {
fac *= k;
ans = (ans + (fac * dp[n][k]) % mod) % mod;
}
return ans;
} // Driver code int main()
{ int n = 5;
// function call
cout << operation(n) << endl;
return 0;
} |
import java.util.*;
public class Main {
static final int mod = 1000000007 ;
static int operation( int n) {
int [][] dp = new int [n+ 1 ][n+ 1 ];
// Initialize base cases
for ( int i = 0 ; i <= n; i++) {
dp[i][ 0 ] = 0 ;
dp[i][i] = 1 ;
}
// Fill the DP table in a bottom-up manner
for ( int i = 1 ; i <= n; i++) {
for ( int j = 1 ; j < i; j++) {
dp[i][j] = (j * dp[i- 1 ][j] + dp[i- 1 ][j- 1 ]) % mod;
}
dp[i][i] = 1 ;
}
// Calculate the answer using the DP table
long ans = 0 , fac = 1 ;
for ( int k = 1 ; k <= n; k++) {
fac *= k;
ans = (ans + (fac * dp[n][k]) % mod) % mod;
}
return ( int )ans;
}
// Driver code
public static void main(String[] args) {
int n = 5 ;
// function call
System.out.println(operation(n));
}
} |
mod = 10 * * 9 + 7
def operation(n):
dp = [[ 0 for j in range (n + 1 )] for i in range (n + 1 )]
# Initialize base cases
for i in range (n + 1 ):
dp[i][ 0 ] = 0
dp[i][i] = 1
# Fill the DP table in a bottom-up manner
for i in range ( 1 , n + 1 ):
for j in range ( 1 , i):
dp[i][j] = (j * dp[i - 1 ][j] + dp[i - 1 ][j - 1 ]) % mod
dp[i][i] = 1
# Calculate the answer using the DP table
ans, fac = 0 , 1
for k in range ( 1 , n + 1 ):
fac * = k
ans = (ans + (fac * dp[n][k]) % mod) % mod
return ans
# Driver code n = 5
print (operation(n))
|
using System;
using System.Collections.Generic;
class Solution {
static int mod = 1000000007;
static int operation( int n)
{
// 2D array to store the DP values
int [][] dp = new int [n + 1][];
// Initialize base cases
for ( int i = 0; i <= n; i++) {
dp[i] = new int [n + 1];
dp[i][0] = 0;
dp[i][i] = 1;
}
// Fill the DP table in a bottom-up manner
for ( int i = 1; i <= n; i++) {
for ( int j = 1; j < i; j++) {
dp[i][j]
= (j * dp[i - 1][j] + dp[i - 1][j - 1])
% mod;
}
dp[i][i] = 1;
}
// Calculate the answer using the DP table
long ans = 0, fac = 1;
for ( int k = 1; k <= n; k++) {
fac *= k;
ans = (ans + (fac * dp[n][k]) % mod) % mod;
}
return ( int )ans;
}
// Driver code
static void Main( string [] args)
{
int n = 5;
// Function call
Console.WriteLine(operation(n));
}
} // This code is contributed by user_dtewbxkn77n |
const mod = 10**9 + 7; function operation(n) {
let dp = Array.from(Array(n+1), () => new Array(n+1).fill(0));
// Initialize base cases
for (let i = 0; i <= n; i++) {
dp[i][0] = 0;
dp[i][i] = 1;
}
// Fill the DP table in a bottom-up manner
for (let i = 1; i <= n; i++) {
for (let j = 1; j < i; j++) {
dp[i][j] = (j * dp[i-1][j] + dp[i-1][j-1]) % mod;
}
dp[i][i] = 1;
}
// Calculate the answer using the DP table
let ans = 0, fac = 1;
for (let k = 1; k <= n; k++) {
fac *= k;
ans = (ans + (fac * dp[n][k]) % mod) % mod;
}
return ans;
} // Driver code let n = 5; console.log(operation(n)); |
541
Time Complexity: O(N*N)
Auxiliary Space: O(N*N)