📌  相关文章
📜  使用给定操作为NK块着色的方法数量

📅  最后修改于: 2021-05-17 20:20:35             🧑  作者: Mango

给定N个块,其中K着色。这K个彩色块由数组arr []表示。任务是计算对剩余的未着色块进行着色的方式,以使着色块中只有相邻块中的任何一个可以在一个步骤中着色。用模10 9 +7打印答案。
例子:

天真的方法:这个想法是使用递归。步骤如下:

  1. 从1到N遍历每个块。
  2. 如果当前块(例如b )未着色,则检查相邻块之一是否已着色。
  3. 如果相邻的块已着色,则为当前块着色,并递归迭代以找到下一个未着色的块。
  4. 然后,在上述递归调用结束之后,为该块引用上一个递归调用对该块上色,并对下一个未上色的块重复上述步骤。
  5. 在上述所有递归调用中,对块进行着色的次数给出了对未着色块进行着色的方法数量。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
const int mod = 1000000007;
 
// Recursive function to count the ways
int countWays(int colored[], int count,
              int n)
{
 
    // Base case
    if (count == n) {
        return 1;
    }
 
    // Intialise answer to 0
    int answer = 0;
 
    // Color each uncolored block according
    // to the given condition
    for (int i = 1; i < n + 1; i++) {
 
        // If any block is uncolored
        if (colored[i] == 0) {
 
            // Check if adjacent blocks
            // are colored or not
            if (colored[i - 1] == 1
                || colored[i + 1] == 1) {
 
                // Color the block
                colored[i] = 1;
 
                // recursively iterate for
                // next uncolored block
                answer = (answer
                          + countWays(colored,
                                      count + 1,
                                      n))
                         % mod;
 
                // Uncolored for the next
                // recursive call
                colored[i] = 0;
            }
        }
    }
 
    // Return the final count
    return answer;
}
 
// Function to count the ways to color
// block
int waysToColor(int arr[], int n, int k)
{
 
    // Mark which blocks are colored in
    // each recursive step
    int colored[n + 2] = { 0 };
 
    for (int i = 0; i < k; i++) {
        colored[arr[i]] = 1;
    }
 
    // Function call to count the ways
    return countWays(colored, k, n);
}
 
// Driver Code
int main()
{
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int arr[K] = { 1, 2, 6 };
 
    // Function call
    cout << waysToColor(arr, N, K);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG{
 
static int mod = 1000000007;
 
// Recursive function to count the ways
static int countWays(int colored[],
                     int count, int n)
{
 
    // Base case
    if (count == n)
    {
        return 1;
    }
 
    // Intialise answer to 0
    int answer = 0;
 
    // Color each uncolored block according
    // to the given condition
    for (int i = 1; i < n + 1; i++)
    {
 
        // If any block is uncolored
        if (colored[i] == 0)
        {
 
            // Check if adjacent blocks
            // are colored or not
            if (colored[i - 1] == 1 ||
                colored[i + 1] == 1)
            {
 
                // Color the block
                colored[i] = 1;
 
                // recursively iterate for
                // next uncolored block
                answer = (answer +
                          countWays(colored,
                                    count + 1,
                                    n)) % mod;
 
                // Uncolored for the next
                // recursive call
                colored[i] = 0;
            }
        }
    }
 
    // Return the final count
    return answer;
}
 
// Function to count the ways to color
// block
static int waysToColor(int arr[],
                       int n, int k)
{
 
    // Mark which blocks are colored in
    // each recursive step
    int colored[] = new int[n + 2];
 
    for (int i = 0; i < k; i++)
    {
        colored[arr[i]] = 1;
    }
 
    // Function call to count the ways
    return countWays(colored, k, n);
}
 
// Driver Code
public static void main(String[] args)
{
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int arr[] = { 1, 2, 6 };
 
    // Function call
    System.out.print(waysToColor(arr, N, K));
}
}
 
// This code is contributed by sapnasingh4991


Python3
# Python3 program for the above approach
mod = 1000000007
 
# Recursive function to count the ways
def countWays(colored, count, n):
 
    # Base case
    if (count == n):
        return 1
 
    # Intialise answer to 0
    answer = 0
 
    # Color each uncolored block according
    # to the given condition
    for i in range(1, n + 1):
 
        # If any block is uncolored
        if (colored[i] == 0):
 
            # Check if adjacent blocks
            # are colored or not
            if (colored[i - 1] == 1 or
                colored[i + 1] == 1):
 
                # Color the block
                colored[i] = 1
 
                # recursively iterate for
                # next uncolored block
                answer = ((answer +
                           countWays(colored,
                                     count + 1,
                                       n)) % mod)
 
                # Uncolored for the next
                # recursive call
                colored[i] = 0
 
    # Return the final count
    return answer
 
# Function to count the ways to color
# block
def waysToColor( arr, n, k):
 
    # Mark which blocks are colored in
    # each recursive step
    colored = [0] * (n + 2)
     
    for i in range(k):
        colored[arr[i]] = 1
 
    # Function call to count the ways
    return countWays(colored, k, n)
 
# Driver Code
if __name__ == "__main__":
     
    # Number of blocks
    N = 6
 
    # Number of colored blocks
    K = 3
    arr = [ 1, 2, 6 ]
 
    # Function call
    print(waysToColor(arr, N, K))
 
# This code is contributed by chitranayal


C#
// C# program for the above approach
using System;
class GFG{
 
static int mod = 1000000007;
 
// Recursive function to count the ways
static int countWays(int []colored,
                     int count, int n)
{
 
    // Base case
    if (count == n)
    {
        return 1;
    }
 
    // Intialise answer to 0
    int answer = 0;
 
    // Color each uncolored block according
    // to the given condition
    for (int i = 1; i < n + 1; i++)
    {
 
        // If any block is uncolored
        if (colored[i] == 0)
        {
 
            // Check if adjacent blocks
            // are colored or not
            if (colored[i - 1] == 1 ||
                colored[i + 1] == 1)
            {
 
                // Color the block
                colored[i] = 1;
 
                // recursively iterate for
                // next uncolored block
                answer = (answer +
                          countWays(colored,
                                    count + 1,
                                    n)) % mod;
 
                // Uncolored for the next
                // recursive call
                colored[i] = 0;
            }
        }
    }
 
    // Return the final count
    return answer;
}
 
// Function to count the ways to color
// block
static int waysToColor(int []arr,
                    int n, int k)
{
 
    // Mark which blocks are colored in
    // each recursive step
    int []colored = new int[n + 2];
 
    for (int i = 0; i < k; i++)
    {
        colored[arr[i]] = 1;
    }
 
    // Function call to count the ways
    return countWays(colored, k, n);
}
 
// Driver Code
public static void Main()
{
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int []arr = { 1, 2, 6 };
 
    // Function call
    Console.Write(waysToColor(arr, N, K));
}
}
 
// This code is contributed by Code_Mech


C++
// C++ program for the above approach
#include 
using namespace std;
 
const int mod = 1000000007;
 
// Function to count the ways to color
// block
int waysToColor(int arr[], int n, int k)
{
    // For storing powers of 2
    int powOf2[500] = { 0 };
 
    // For storing binomial coefficient
    // values
    int c[500][500];
 
    // Calculating binomial coefficient
    // using DP
    for (int i = 0; i <= n; i++) {
 
        c[i][0] = 1;
        for (int j = 1; j <= i; j++) {
            c[i][j] = (c[i - 1][j]
                       + c[i - 1][j - 1])
                      % mod;
        }
    }
 
    powOf2[0] = powOf2[1] = 1;
 
    // Calculating powers of 2
    for (int i = 2; i <= n; i++) {
 
        powOf2[i] = powOf2[i - 1] * 2 % mod;
    }
 
    int rem = n - k;
    arr[k++] = n + 1;
 
    // Sort the indices to calculate
    // length of each section
    sort(arr, arr + k);
 
    // Initialise answer to 1
    int answer = 1;
 
    for (int i = 0; i < k; i++) {
 
        // Find the length of each section
        int x = arr[i] - (i - 1 >= 0
                              ? arr[i - 1]
                              : 0)
                - 1;
 
        // Merge this section
        answer *= c[rem][x] % mod * (i != 0
                                             && i != k - 1
                                         ? powOf2[x]
                                         : 1)
                  % mod;
        rem -= x;
    }
 
    // Return the final count
    return answer;
}
 
// Driver Code
int main()
{
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int arr[K] = { 1, 2, 6 };
 
    // Function call
    cout << waysToColor(arr, N, K);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
static int mod = 1000000007;
 
// Function to count the ways to color
// block
static int waysToColor(int arr[], int n, int k)
{
     
    // For storing powers of 2
    int powOf2[] = new int[500];
 
    // For storing binomial coefficient
    // values
    int [][]c = new int[500][500];
 
    // Calculating binomial coefficient
    // using DP
    for(int i = 0; i <= n; i++)
    {
       c[i][0] = 1;
       for(int j = 1; j <= i; j++)
       {
          c[i][j] = (c[i - 1][j] +
                     c[i - 1][j - 1]) % mod;
       }
    }
 
    powOf2[0] = powOf2[1] = 1;
 
    // Calculating powers of 2
    for(int i = 2; i <= n; i++)
    {
       powOf2[i] = powOf2[i - 1] * 2 % mod;
    }
 
    int rem = n - k;
    arr[k++] = n + 1;
     
    // Sort the indices to calculate
    // length of each section
    Arrays.sort(arr);
 
    // Initialise answer to 1
    int answer = 1;
 
    for(int i = 0; i < k; i++)
    {
         
       // Find the length of each section
       int x = arr[i] - (i - 1 >= 0 ?
                     arr[i - 1] : 0) - 1;
        
       // Merge this section
       answer *= c[rem][x] % mod * (i != 0 &&
                                    i != k - 1 ?
                                    powOf2[x] : 1) %
                                    mod;
       rem -= x;
    }
     
    // Return the final count
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int arr[] = { 1, 2, 6 ,0 };
 
    // Function call
    System.out.print(waysToColor(arr, N, K));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 program for the above approach
mod = 1000000007
  
# Function to count the ways to color
# block
def waysToColor(arr, n, k):
     
    global mod
 
    # For storing powers of 2
    powOf2 = [0 for i in range(500)]
  
    # For storing binomial coefficient
    # values
    c = [[0 for i in range(500)] for j in range(500)]
  
    # Calculating binomial coefficient
    # using DP
    for i in range(n + 1):
  
        c[i][0] = 1;
         
        for j in range(1, i + 1):
         
            c[i][j] = (c[i - 1][j]+ c[i - 1][j - 1])% mod;
  
    powOf2[0] = 1
    powOf2[1] = 1;
  
    # Calculating powers of 2
    for i in range(2, n + 1):
  
        powOf2[i] = (powOf2[i - 1] * 2) % mod;
     
    rem = n - k;
    arr[k] = n + 1;
    k += 1
  
    # Sort the indices to calculate
    # length of each section
    arr.sort()
  
    # Initialise answer to 1
    answer = 1;
     
    for i in range(k):
         
        x = 0
         
        # Find the length of each section
        if i - 1 >= 0:
            x = arr[i] - arr[i - 1] -1
        else:
            x = arr[i] - 1
  
        # Merge this section
        answer = answer * (c[rem][x] % mod) * ((powOf2[x] if (i != 0 and i != k - 1) else 1))% mod
        rem -= x;
  
    # Return the final count
    return answer;
 
# Driver Code
if __name__=='__main__':
  
    # Number of blocks
    N = 6;
  
    # Number of colored blocks
    K = 3;
    arr = [ 1, 2, 6, 0]
  
    # Function call
    print(waysToColor(arr, N, K))
 
# This code is contributed by rutvik_56


C#
// C# program for the above approach
using System;
class GFG{
 
static int mod = 1000000007;
 
// Function to count the ways to color
// block
static int waysToColor(int []arr, int n, int k)
{
     
    // For storing powers of 2
    int []powOf2 = new int[500];
 
    // For storing binomial coefficient
    // values
    int [,]c = new int[500, 500];
 
    // Calculating binomial coefficient
    // using DP
    for(int i = 0; i <= n; i++)
    {
        c[i, 0] = 1;
        for(int j = 1; j <= i; j++)
        {
            c[i, j] = (c[i - 1, j] +
                       c[i - 1, j - 1]) % mod;
        }
    }
 
    powOf2[0] = powOf2[1] = 1;
 
    // Calculating powers of 2
    for(int i = 2; i <= n; i++)
    {
        powOf2[i] = powOf2[i - 1] * 2 % mod;
    }
 
    int rem = n - k;
    arr[k++] = n + 1;
     
    // Sort the indices to calculate
    // length of each section
    Array.Sort(arr);
 
    // Initialise answer to 1
    int answer = 1;
 
    for(int i = 0; i < k; i++)
    {
         
        // Find the length of each section
        int x = arr[i] - (i - 1 >= 0 ?
                arr[i - 1] : 0) - 1;
             
        // Merge this section
        answer *= c[rem, x] % mod * (i != 0 &&
                                     i != k - 1 ?
                                     powOf2[x] : 1) %
                                     mod;
        rem -= x;
    }
     
    // Return the readonly count
    return answer;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int []arr = { 1, 2, 6, 0 };
 
    // Function call
    Console.Write(waysToColor(arr, N, K));
}
}
 
// This code is contributed by 29AjayKumar


输出:
4

时间复杂度: O(N NK )
高效方法:为了有效解决此问题,我们将使用置换和组合的概念。步骤如下:

  1. 如果两个连续的彩色块之间的块数是x,则给这些块集着色的方式的数目由下式给出:
  1. 给每组未着色的块着色是彼此独立的。假设一个部分有x个块,另一部分有y个块。要找到两个部分合并时的总组合,可通过以下方式给出:
  1. 对有色块索引进行排序,以找到每个无色块部分的长度,并使用上述公式迭代并找到每两个部分的组合。
  2. 使用本文讨论的方法找到二项式系数。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
const int mod = 1000000007;
 
// Function to count the ways to color
// block
int waysToColor(int arr[], int n, int k)
{
    // For storing powers of 2
    int powOf2[500] = { 0 };
 
    // For storing binomial coefficient
    // values
    int c[500][500];
 
    // Calculating binomial coefficient
    // using DP
    for (int i = 0; i <= n; i++) {
 
        c[i][0] = 1;
        for (int j = 1; j <= i; j++) {
            c[i][j] = (c[i - 1][j]
                       + c[i - 1][j - 1])
                      % mod;
        }
    }
 
    powOf2[0] = powOf2[1] = 1;
 
    // Calculating powers of 2
    for (int i = 2; i <= n; i++) {
 
        powOf2[i] = powOf2[i - 1] * 2 % mod;
    }
 
    int rem = n - k;
    arr[k++] = n + 1;
 
    // Sort the indices to calculate
    // length of each section
    sort(arr, arr + k);
 
    // Initialise answer to 1
    int answer = 1;
 
    for (int i = 0; i < k; i++) {
 
        // Find the length of each section
        int x = arr[i] - (i - 1 >= 0
                              ? arr[i - 1]
                              : 0)
                - 1;
 
        // Merge this section
        answer *= c[rem][x] % mod * (i != 0
                                             && i != k - 1
                                         ? powOf2[x]
                                         : 1)
                  % mod;
        rem -= x;
    }
 
    // Return the final count
    return answer;
}
 
// Driver Code
int main()
{
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int arr[K] = { 1, 2, 6 };
 
    // Function call
    cout << waysToColor(arr, N, K);
    return 0;
}

Java

// Java program for the above approach
import java.util.*;
 
class GFG{
 
static int mod = 1000000007;
 
// Function to count the ways to color
// block
static int waysToColor(int arr[], int n, int k)
{
     
    // For storing powers of 2
    int powOf2[] = new int[500];
 
    // For storing binomial coefficient
    // values
    int [][]c = new int[500][500];
 
    // Calculating binomial coefficient
    // using DP
    for(int i = 0; i <= n; i++)
    {
       c[i][0] = 1;
       for(int j = 1; j <= i; j++)
       {
          c[i][j] = (c[i - 1][j] +
                     c[i - 1][j - 1]) % mod;
       }
    }
 
    powOf2[0] = powOf2[1] = 1;
 
    // Calculating powers of 2
    for(int i = 2; i <= n; i++)
    {
       powOf2[i] = powOf2[i - 1] * 2 % mod;
    }
 
    int rem = n - k;
    arr[k++] = n + 1;
     
    // Sort the indices to calculate
    // length of each section
    Arrays.sort(arr);
 
    // Initialise answer to 1
    int answer = 1;
 
    for(int i = 0; i < k; i++)
    {
         
       // Find the length of each section
       int x = arr[i] - (i - 1 >= 0 ?
                     arr[i - 1] : 0) - 1;
        
       // Merge this section
       answer *= c[rem][x] % mod * (i != 0 &&
                                    i != k - 1 ?
                                    powOf2[x] : 1) %
                                    mod;
       rem -= x;
    }
     
    // Return the final count
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int arr[] = { 1, 2, 6 ,0 };
 
    // Function call
    System.out.print(waysToColor(arr, N, K));
}
}
 
// This code is contributed by 29AjayKumar

Python3

# Python3 program for the above approach
mod = 1000000007
  
# Function to count the ways to color
# block
def waysToColor(arr, n, k):
     
    global mod
 
    # For storing powers of 2
    powOf2 = [0 for i in range(500)]
  
    # For storing binomial coefficient
    # values
    c = [[0 for i in range(500)] for j in range(500)]
  
    # Calculating binomial coefficient
    # using DP
    for i in range(n + 1):
  
        c[i][0] = 1;
         
        for j in range(1, i + 1):
         
            c[i][j] = (c[i - 1][j]+ c[i - 1][j - 1])% mod;
  
    powOf2[0] = 1
    powOf2[1] = 1;
  
    # Calculating powers of 2
    for i in range(2, n + 1):
  
        powOf2[i] = (powOf2[i - 1] * 2) % mod;
     
    rem = n - k;
    arr[k] = n + 1;
    k += 1
  
    # Sort the indices to calculate
    # length of each section
    arr.sort()
  
    # Initialise answer to 1
    answer = 1;
     
    for i in range(k):
         
        x = 0
         
        # Find the length of each section
        if i - 1 >= 0:
            x = arr[i] - arr[i - 1] -1
        else:
            x = arr[i] - 1
  
        # Merge this section
        answer = answer * (c[rem][x] % mod) * ((powOf2[x] if (i != 0 and i != k - 1) else 1))% mod
        rem -= x;
  
    # Return the final count
    return answer;
 
# Driver Code
if __name__=='__main__':
  
    # Number of blocks
    N = 6;
  
    # Number of colored blocks
    K = 3;
    arr = [ 1, 2, 6, 0]
  
    # Function call
    print(waysToColor(arr, N, K))
 
# This code is contributed by rutvik_56

C#

// C# program for the above approach
using System;
class GFG{
 
static int mod = 1000000007;
 
// Function to count the ways to color
// block
static int waysToColor(int []arr, int n, int k)
{
     
    // For storing powers of 2
    int []powOf2 = new int[500];
 
    // For storing binomial coefficient
    // values
    int [,]c = new int[500, 500];
 
    // Calculating binomial coefficient
    // using DP
    for(int i = 0; i <= n; i++)
    {
        c[i, 0] = 1;
        for(int j = 1; j <= i; j++)
        {
            c[i, j] = (c[i - 1, j] +
                       c[i - 1, j - 1]) % mod;
        }
    }
 
    powOf2[0] = powOf2[1] = 1;
 
    // Calculating powers of 2
    for(int i = 2; i <= n; i++)
    {
        powOf2[i] = powOf2[i - 1] * 2 % mod;
    }
 
    int rem = n - k;
    arr[k++] = n + 1;
     
    // Sort the indices to calculate
    // length of each section
    Array.Sort(arr);
 
    // Initialise answer to 1
    int answer = 1;
 
    for(int i = 0; i < k; i++)
    {
         
        // Find the length of each section
        int x = arr[i] - (i - 1 >= 0 ?
                arr[i - 1] : 0) - 1;
             
        // Merge this section
        answer *= c[rem, x] % mod * (i != 0 &&
                                     i != k - 1 ?
                                     powOf2[x] : 1) %
                                     mod;
        rem -= x;
    }
     
    // Return the readonly count
    return answer;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Number of blocks
    int N = 6;
 
    // Number of colored blocks
    int K = 3;
    int []arr = { 1, 2, 6, 0 };
 
    // Function call
    Console.Write(waysToColor(arr, N, K));
}
}
 
// This code is contributed by 29AjayKumar
输出:
4

时间复杂度: O(N 2 )