📌  相关文章
📜  从给定范围内将N分解为K个数字之和的方式数量

📅  最后修改于: 2021-04-24 19:00:30             🧑  作者: Mango

给定四个正整数N,K,LR ,任务是将N分解为位于[L,R]范围内的K个数字之和。
注意:由于方式的数量可能非常大。输出模1000000007的答案。
例子:

天真的方法
我们可以使用递归来解决问题。在递归的每个步骤中,尝试使大小为L到R的组全部
递归中有两个参数会发生变化:

  • pos –组号
  • 左–剩余的N数量要分配

下面是上述方法的实现:

C++
// C++ implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
 
#include 
 
using namespace std;
 
const int mod = 1000000007;
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
int calculate(int pos, int left,
              int k, int L, int R)
{
    // Base Case
    if (pos == k) {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // if N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    int answer = 0;
 
    // put all possible values
    // greater equal to prev
    for (int i = L; i <= R; i++) {
        if (i > left)
            break;
        answer = (answer + calculate(pos + 1,
                                     left - i, k, L, R))
                 % mod;
    }
    return answer;
}
 
// Function to count the number of
// ways to divide the number N
int countWaystoDivide(int n, int k,
                      int L, int R)
{
    return calculate(0, n, k, L, R);
}
 
// Driver Code
int main()
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    cout << countWaystoDivide(N, K, L, R);
    return 0;
}


Java
// Java implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
class GFG{
 
static int mod = 1000000007;
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
static int calculate(int pos, int left,
                     int k, int L, int R)
{
    // Base Case
    if (pos == k)
    {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // If N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    int answer = 0;
 
    // Put all possible values
    // greater equal to prev
    for(int i = L; i <= R; i++)
    {
       if (i > left)
           break;
       answer = ((answer +
                  calculate(pos + 1,left - i,
                            k, L, R)) % mod);
    }
    return answer;
}
 
// Function to count the number of
// ways to divide the number N
static int countWaystoDivide(int n, int k,
                             int L, int R)
{
    return calculate(0, n, k, L, R);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    System.out.print(countWaystoDivide(N, K, L, R));
}
}
 
// This code is contributed by Amit Katiyar


Python3
# Python3 implementation to count the
# number of ways to divide N in K
# groups such that each group
# has elements in range [L, R]
 
mod = 1000000007
 
# Function to count the number
# of ways to divide the number N
# in K groups such that each group
# has number of elements in range [L, R]
def calculate(pos, left, k, L, R):
     
    # Base Case
    if (pos == k):
        if (left == 0):
            return 1
        else:
            return 0
 
    # If N is divides completely
    # into less than k groups
    if (left == 0):
        return 0
         
    answer = 0
 
    # Put all possible values
    # greater equal to prev
    for i in range(L, R + 1):
        if (i > left):
            break
        answer = (answer +
                  calculate(pos + 1,
                            left - i, k, L, R)) % mod
    return answer
 
# Function to count the number of
# ways to divide the number N
def countWaystoDivide(n, k, L, R):
    return calculate(0, n, k, L, R)
 
# Driver Code
N = 12
K = 3
L = 1
R = 5
 
print(countWaystoDivide(N, K, L, R))
     
# This code is contributed by divyamohan123


C#
// C# implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
using System;
 
class GFG{
 
static int mod = 1000000007;
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
static int calculate(int pos, int left,
                     int k, int L, int R)
{
     
    // Base Case
    if (pos == k)
    {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // If N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    int answer = 0;
 
    // Put all possible values
    // greater equal to prev
    for(int i = L; i <= R; i++)
    {
       if (i > left)
           break;
       answer = ((answer +
                  calculate(pos + 1,left - i,
                            k, L, R)) % mod);
    }
    return answer;
}
 
// Function to count the number of
// ways to divide the number N
static int countWaystoDivide(int n, int k,
                             int L, int R)
{
    return calculate(0, n, k, L, R);
}
 
// Driver Code
public static void Main(String[] args)
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    Console.Write(countWaystoDivide(N, K, L, R));
}
}
 
// This code is contributed by Amit Katiyar


C++
// C++ implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
 
#include 
 
using namespace std;
 
const int mod = 1000000007;
 
// DP Table
int dp[1000][1000];
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
int calculate(int pos, int left,
              int k, int L, int R)
{
    // Base Case
    if (pos == k) {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // if N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    // If the subproblem has been
    // solved, use the value
    if (dp[pos][left] != -1)
        return dp[pos][left];
 
    int answer = 0;
 
    // put all possible values
    // greater equal to prev
    for (int i = L; i <= R; i++) {
        if (i > left)
            break;
        answer = (answer + calculate(pos + 1,
                                     left - i, k, L, R))
                 % mod;
    }
    return dp[pos][left] = answer;
}
 
// Function to count the number of
// ways to divide the number N
int countWaystoDivide(int n, int k,
                      int L, int R)
{
    // Intialize DP Table as -1
    memset(dp, -1, sizeof(dp));
    return calculate(0, n, k, L, R);
}
 
// Driver Code
int main()
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    cout << countWaystoDivide(N, K, L, R);
    return 0;
}


Java
// Java implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
class GFG{
 
static int mod = 1000000007;
 
// DP Table
static int [][]dp = new int[1000][1000];
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
static int calculate(int pos, int left,
                     int k, int L, int R)
{
     
    // Base Case
    if (pos == k)
    {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // If N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    // If the subproblem has been
    // solved, use the value
    if (dp[pos][left] != -1)
        return dp[pos][left];
 
    int answer = 0;
 
    // Put all possible values
    // greater equal to prev
    for(int i = L; i <= R; i++)
    {
       if (i > left)
           break;
       answer = (answer + calculate(pos + 1, left - i,
                                      k, L, R)) % mod;
    }
    return dp[pos][left] = answer;
}
 
// Function to count the number of
// ways to divide the number N
static int countWaystoDivide(int n, int k,
                             int L, int R)
{
     
    // Intialize DP Table as -1
    for(int i = 0; i < 1000; i++)
    {
       for(int j = 0; j < 1000; j++)
       {
          dp[i][j] = -1;
       }
    }
    return calculate(0, n, k, L, R);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    System.out.print(countWaystoDivide(N, K, L, R));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 implementation to count the
# number of ways to divide N in K
# groups such that each group
# has elements in range [L, R]
mod = 1000000007
  
# DP Table
dp = [[-1 for j in range(1000)]
          for i in range(1000)]
  
# Function to count the number
# of ways to divide the number N
# in K groups such that each group
# has number of elements in range [L, R]
def calculate(pos, left, k, L, R):
 
    # Base Case
    if (pos == k):
        if (left == 0):
            return 1
        else:
            return 0
 
    # if N is divides completely
    # into less than k groups
    if (left == 0):
        return 0
  
    # If the subproblem has been
    # solved, use the value
    if (dp[pos][left] != -1):
        return dp[pos][left]
  
    answer = 0
  
    # put all possible values
    # greater equal to prev
    for i in range(L, R + 1):
        if (i > left):
            break
         
        answer = (answer +
                  calculate(pos + 1,
                           left - i,
                           k, L, R)) % mod
     
    dp[pos][left] = answer
     
    return answer
 
# Function to count the number of
# ways to divide the number N
def countWaystoDivide(n, k, L, R):
     
    return calculate(0, n, k, L, R)
 
# Driver code
if __name__=="__main__":
     
    N = 12
    K = 3
    L = 1
    R = 5
  
    print(countWaystoDivide(N, K, L, R))
     
# This code is contributed by rutvik_56


C#
// C# implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
using System;
class GFG{
 
static int mod = 1000000007;
 
// DP Table
static int [,]dp = new int[1000, 1000];
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
static int calculate(int pos, int left,
                     int k, int L, int R)
{
     
    // Base Case
    if (pos == k)
    {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // If N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    // If the subproblem has been
    // solved, use the value
    if (dp[pos, left] != -1)
        return dp[pos, left];
 
    int answer = 0;
 
    // Put all possible values
    // greater equal to prev
    for(int i = L; i <= R; i++)
    {
        if (i > left)
            break;
        answer = (answer + calculate(pos + 1, left - i,
                                       k, L, R)) % mod;
    }
    return dp[pos, left] = answer;
}
 
// Function to count the number of
// ways to divide the number N
static int countWaystoDivide(int n, int k,
                             int L, int R)
{
     
    // Intialize DP Table as -1
    for(int i = 0; i < 1000; i++)
    {
        for(int j = 0; j < 1000; j++)
        {
            dp[i, j] = -1;
        }
    }
    return calculate(0, n, k, L, R);
}
 
// Driver Code
public static void Main()
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    Console.Write(countWaystoDivide(N, K, L, R));
}
}
 
// This code is contributed by Code_Mech


输出:
10


时间复杂度: O(N K )

高效的方法:在以前的方法中,我们可以看到我们正在反复求解子问题,即它遵循“重叠子问题”的属性。因此,我们可以使用DP表记住相同的内容。

下面是上述方法的实现:

C++

// C++ implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
 
#include 
 
using namespace std;
 
const int mod = 1000000007;
 
// DP Table
int dp[1000][1000];
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
int calculate(int pos, int left,
              int k, int L, int R)
{
    // Base Case
    if (pos == k) {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // if N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    // If the subproblem has been
    // solved, use the value
    if (dp[pos][left] != -1)
        return dp[pos][left];
 
    int answer = 0;
 
    // put all possible values
    // greater equal to prev
    for (int i = L; i <= R; i++) {
        if (i > left)
            break;
        answer = (answer + calculate(pos + 1,
                                     left - i, k, L, R))
                 % mod;
    }
    return dp[pos][left] = answer;
}
 
// Function to count the number of
// ways to divide the number N
int countWaystoDivide(int n, int k,
                      int L, int R)
{
    // Intialize DP Table as -1
    memset(dp, -1, sizeof(dp));
    return calculate(0, n, k, L, R);
}
 
// Driver Code
int main()
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    cout << countWaystoDivide(N, K, L, R);
    return 0;
}

Java

// Java implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
class GFG{
 
static int mod = 1000000007;
 
// DP Table
static int [][]dp = new int[1000][1000];
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
static int calculate(int pos, int left,
                     int k, int L, int R)
{
     
    // Base Case
    if (pos == k)
    {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // If N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    // If the subproblem has been
    // solved, use the value
    if (dp[pos][left] != -1)
        return dp[pos][left];
 
    int answer = 0;
 
    // Put all possible values
    // greater equal to prev
    for(int i = L; i <= R; i++)
    {
       if (i > left)
           break;
       answer = (answer + calculate(pos + 1, left - i,
                                      k, L, R)) % mod;
    }
    return dp[pos][left] = answer;
}
 
// Function to count the number of
// ways to divide the number N
static int countWaystoDivide(int n, int k,
                             int L, int R)
{
     
    // Intialize DP Table as -1
    for(int i = 0; i < 1000; i++)
    {
       for(int j = 0; j < 1000; j++)
       {
          dp[i][j] = -1;
       }
    }
    return calculate(0, n, k, L, R);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    System.out.print(countWaystoDivide(N, K, L, R));
}
}
 
// This code is contributed by 29AjayKumar

Python3

# Python3 implementation to count the
# number of ways to divide N in K
# groups such that each group
# has elements in range [L, R]
mod = 1000000007
  
# DP Table
dp = [[-1 for j in range(1000)]
          for i in range(1000)]
  
# Function to count the number
# of ways to divide the number N
# in K groups such that each group
# has number of elements in range [L, R]
def calculate(pos, left, k, L, R):
 
    # Base Case
    if (pos == k):
        if (left == 0):
            return 1
        else:
            return 0
 
    # if N is divides completely
    # into less than k groups
    if (left == 0):
        return 0
  
    # If the subproblem has been
    # solved, use the value
    if (dp[pos][left] != -1):
        return dp[pos][left]
  
    answer = 0
  
    # put all possible values
    # greater equal to prev
    for i in range(L, R + 1):
        if (i > left):
            break
         
        answer = (answer +
                  calculate(pos + 1,
                           left - i,
                           k, L, R)) % mod
     
    dp[pos][left] = answer
     
    return answer
 
# Function to count the number of
# ways to divide the number N
def countWaystoDivide(n, k, L, R):
     
    return calculate(0, n, k, L, R)
 
# Driver code
if __name__=="__main__":
     
    N = 12
    K = 3
    L = 1
    R = 5
  
    print(countWaystoDivide(N, K, L, R))
     
# This code is contributed by rutvik_56

C#

// C# implementation to count the
// number of ways to divide N in K
// groups such that each group
// has elements in range [L, R]
using System;
class GFG{
 
static int mod = 1000000007;
 
// DP Table
static int [,]dp = new int[1000, 1000];
 
// Function to count the number
// of ways to divide the number N
// in K groups such that each group
// has number of elements in range [L, R]
static int calculate(int pos, int left,
                     int k, int L, int R)
{
     
    // Base Case
    if (pos == k)
    {
        if (left == 0)
            return 1;
        else
            return 0;
    }
 
    // If N is divides completely
    // into less than k groups
    if (left == 0)
        return 0;
 
    // If the subproblem has been
    // solved, use the value
    if (dp[pos, left] != -1)
        return dp[pos, left];
 
    int answer = 0;
 
    // Put all possible values
    // greater equal to prev
    for(int i = L; i <= R; i++)
    {
        if (i > left)
            break;
        answer = (answer + calculate(pos + 1, left - i,
                                       k, L, R)) % mod;
    }
    return dp[pos, left] = answer;
}
 
// Function to count the number of
// ways to divide the number N
static int countWaystoDivide(int n, int k,
                             int L, int R)
{
     
    // Intialize DP Table as -1
    for(int i = 0; i < 1000; i++)
    {
        for(int j = 0; j < 1000; j++)
        {
            dp[i, j] = -1;
        }
    }
    return calculate(0, n, k, L, R);
}
 
// Driver Code
public static void Main()
{
    int N = 12;
    int K = 3;
    int L = 1;
    int R = 5;
 
    Console.Write(countWaystoDivide(N, K, L, R));
}
}
 
// This code is contributed by Code_Mech
输出:
10


时间复杂度: O(N 2 )