📌  相关文章
📜  具有相同数量的不同奇数和偶数的 N 位数字的计数

📅  最后修改于: 2021-09-17 06:44:21             🧑  作者: Mango

给定一个正整数N ,任务是计算N位数字的数量,使得数字中不同的奇数和不同的偶数位数相同。

例子:

朴素方法:解决给定问题的最简单方法是生成所有可能的N位数字,并计算那些不同奇数和偶数位数相同的数字。检查所有数字后,打印计数值作为结果的总数字计数。

时间复杂度: O(N *10 N )
辅助空间: O(1)

高效方法:上述方法也可以使用动态规划进行优化,因为上述问题具有重叠子问题和最优子结构。子问题可以存储在dp[][][] 表记忆中,其中dp[index][evenMask][oddMask]存储从第i索引位置到最后的答案,其中evenMask用于确定不同偶数的数量数字中的位数,而oddMask用于使用位掩码确定数字中不同奇数位数的数量。请按照以下步骤解决问题:

  • 初始化一个全局多维数组dp[100][1<<5][1<<5],其中所有值都为 -1,用于存储每个递归调用的结果。
  • 通过执行以下步骤定义一个递归函数,比如countOfNumbers(index, evenMask,oddMask, N)
    • 如果索引的值等于(N + 1),
      • 计算evenMaskoddMask中设置位的计数。
      • 如果它们的计数相同,则不同的偶数和奇数位数相同,因此返回1作为有效的 N 位数。
      • 否则返回0
    • 如果已经计算了状态dp[index][evenMask][oddMask] 的结果,则返回此值dp[index][evenMask][oddMask]
    • 如果当前索引1 ,则可以放置[1-9] 中的任何数字,如果N = 1 ,则也可以放置0
    • 对于所有其他索引,可以放置[0-9] 中的任何数字。
    • 对于任何放置的数字,根据数字的奇偶校验,将evenMaskoddMask 的(digit / 2)设置1 。它表示数字中存在特定数字。由于我们将数字除以2 ,大小为(1 << 5) 的位掩码对于每个oddMaskevenMask就足够了。
    • 进行有效放置后,递归调用(index + 1)countOfNumbers函数。
    • 返回所有可能的有效数字位置的总和作为答案。
  • 完成上述步骤后,打印函数countOfNumbers(1, 0, 0, N ) 返回的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Stores the dp-states
int dp[100][1 << 5][1 << 5];
 
// Recursive Function to find number
// of N-digit numbers which has equal
// count of distinct odd & even digits
int countOfNumbers(int index, int evenMask,
                   int oddMask, int N)
{
    // If index is N + 1
    if (index == N + 1) {
 
        // Find the count of set bits
        // in the evenMask
        int countOfEvenDigits
            = __builtin_popcount(evenMask);
 
        // Find the count of set bits
        // in the oddMask
        int countOfOddDigits
            = __builtin_popcount(oddMask);
 
        // If the count of set bits in both
        // masks are equal then return 1
        // as they have equal number of
        // distinct odd and even digits
        if (countOfOddDigits
            == countOfEvenDigits) {
            return 1;
        }
        return 0;
    }
 
    int& val = dp[index][evenMask][oddMask];
 
    // If the state has already
    // been computed
    if (val != -1)
        return val;
 
    val = 0;
 
    // If current position is 1, then
    // any digit from [1-9] can be
    // placed
 
    // If N = 1, 0 can be also placed
    if (index == 1) {
 
        for (int digit = (N == 1 ? 0 : 1);
             digit <= 9; ++digit) {
 
            // If digit is odd
            if (digit & 1) {
 
                // Set the (digit/2)th bit
                // of the oddMask
                val += countOfNumbers(
                    index + 1, evenMask,
                    oddMask | (1 << (digit / 2)), N);
            }
 
            // Set the (digit/2)th bit
            // of the number evenMask
            else {
 
                val += countOfNumbers(
                    index + 1,
                    evenMask | (1 << (digit / 2)),
                    oddMask, N);
            }
        }
    }
 
    // For remaining positions, any
    // digit from [0-9] can be placed
    else {
        for (int digit = 0;
             digit <= 9; ++digit) {
 
            // If digit is odd
            if (digit & 1) {
 
                // Set the (digit/2)th
                // bit of oddMask
                val += countOfNumbers(
                    index + 1, evenMask,
                    oddMask | (1 << (digit / 2)), N);
            }
 
            else {
 
                // Set the (digit/2)th
                // bit of evenMask
                val += countOfNumbers(
                    index + 1,
                    evenMask | (1 << (digit / 2)),
                    oddMask, N);
            }
        }
    }
 
    // Return the answer
    return val;
}
 
// Function to find number of N-digit
// numbers which has equal count of
// distinct odd and even digits
void countNDigitNumber(int N)
{
 
    // Initialize dp array with -1
    memset(dp, -1, sizeof dp);
 
    // Function Call
    cout << countOfNumbers(1, 0, 0, N);
}
 
// Driver Code
int main()
{
    int N = 3;
    countNDigitNumber(N);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG{
     
// Stores the dp-states
static int[][][] dp = new int[100][1 << 5][1 << 5];
 
// Returns number of set bits in a number
static int __builtin_popcount(int n)
{
    int d, t = 0;
     
    while(n > 0)
    {
        d = n % 2;
        n = n / 2;
         
        if (d == 1)
            t++;
    }
    return t;
}
 
// Recursive Function to find number
// of N-digit numbers which has equal
// count of distinct odd & even digits
static int countOfNumbers(int index, int evenMask,
                          int oddMask, int N)
{
     
    // If index is N + 1
    if (index == N + 1)
    {
         
        // Find the count of set bits
        // in the evenMask
        int countOfEvenDigits = __builtin_popcount(evenMask);
 
        // Find the count of set bits
        // in the oddMask
        int countOfOddDigits = __builtin_popcount(oddMask);
 
        // If the count of set bits in both
        // masks are equal then return 1
        // as they have equal number of
        // distinct odd and even digits
        if (countOfOddDigits == countOfEvenDigits)
        {
            return 1;
        }
        return 0;
    }
 
    int val = dp[index][evenMask][oddMask];
 
    // If the state has already
    // been computed
    if (val != -1)
        return val;
 
    val = 0;
 
    // If current position is 1, then
    // any digit from [1-9] can be
    // placed
 
    // If N = 1, 0 can be also placed
    if (index == 1)
    {
        for(int digit = (N == 1 ? 0 : 1);
                digit <= 9; ++digit)
        {
             
            // If digit is odd
            if ((digit & 1) != 0)
            {
                 
                // Set the (digit/2)th bit
                // of the oddMask
                val += countOfNumbers(
                    index + 1, evenMask,
                    oddMask | (1 << (digit / 2)), N);
            }
 
            // Set the (digit/2)th bit
            // of the number evenMask
            else
            {
                val += countOfNumbers(
                    index + 1,
                    evenMask | (1 << (digit / 2)),
                    oddMask, N);
            }
        }
    }
 
    // For remaining positions, any
    // digit from [0-9] can be placed
    else
    {
        for(int digit = 0; digit <= 9; ++digit)
        {
             
            // If digit is odd
            if ((digit & 1) != 0)
            {
                 
                // Set the (digit/2)th
                // bit of oddMask
                val += countOfNumbers(
                    index + 1, evenMask,
                    oddMask | (1 << (digit / 2)), N);
            }
            else
            {
                 
                // Set the (digit/2)th
                // bit of evenMask
                val += countOfNumbers(
                    index + 1,
                    evenMask | (1 << (digit / 2)),
                    oddMask, N);
            }
        }
    }
 
    // Return the answer
    return val;
}
 
// Function to find number of N-digit
// numbers which has equal count of
// distinct odd and even digits
static void countNDigitNumber(int N)
{
     
    // Initialize dp array with -1
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < (1 << 5); j++)
        {
            for(int k = 0; k < (1 << 5); k++)
            {
                dp[i][j][k] = -1;
            }
        }
    }
     
    // Function Call
    System.out.println(countOfNumbers(1, 0, 0, N));
}
 
// Driver code
public static void main(String[] args)
{
    int N = 3;
    countNDigitNumber(N);
}
}
 
// This code is contributed by sanjoy_62


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Stores the dp-states
static int[,,] dp = new int[100, 1 << 5, 1 << 5];
 
// Returns number of set bits in a number
static int __builtin_popcount(int n)
{
    int d, t = 0;
     
    while(n > 0)
    {
        d = n % 2;
        n = n / 2;
         
        if (d == 1)
            t++;
    }
    return t;
}
 
// Recursive Function to find number
// of N-digit numbers which has equal
// count of distinct odd & even digits
static int countOfNumbers(int index, int evenMask,
                          int oddMask, int N)
{
     
    // If index is N + 1
    if (index == N + 1)
    {
         
        // Find the count of set bits
        // in the evenMask
        int countOfEvenDigits = __builtin_popcount(evenMask);
 
        // Find the count of set bits
        // in the oddMask
        int countOfOddDigits = __builtin_popcount(oddMask);
 
        // If the count of set bits in both
        // masks are equal then return 1
        // as they have equal number of
        // distinct odd and even digits
        if (countOfOddDigits == countOfEvenDigits)
        {
            return 1;
        }
        return 0;
    }
 
    int val = dp[index, evenMask, oddMask];
 
    // If the state has already
    // been computed
    if (val != -1)
        return val;
 
    val = 0;
 
    // If current position is 1, then
    // any digit from [1-9] can be
    // placed
 
    // If N = 1, 0 can be also placed
    if (index == 1)
    {
        for(int digit = (N == 1 ? 0 : 1);
                digit <= 9; ++digit)
        {
             
            // If digit is odd
            if ((digit & 1) != 0)
            {
                 
                // Set the (digit/2)th bit
                // of the oddMask
                val += countOfNumbers(
                    index + 1, evenMask,
                    oddMask | (1 << (digit / 2)), N);
            }
 
            // Set the (digit/2)th bit
            // of the number evenMask
            else
            {
                val += countOfNumbers(
                    index + 1,
                    evenMask | (1 << (digit / 2)),
                    oddMask, N);
            }
        }
    }
 
    // For remaining positions, any
    // digit from [0-9] can be placed
    else
    {
        for(int digit = 0; digit <= 9; ++digit)
        {
             
            // If digit is odd
            if ((digit & 1) != 0)
            {
                 
                // Set the (digit/2)th
                // bit of oddMask
                val += countOfNumbers(
                    index + 1, evenMask,
                    oddMask | (1 << (digit / 2)), N);
            }
            else
            {
                 
                // Set the (digit/2)th
                // bit of evenMask
                val += countOfNumbers(
                    index + 1,
                    evenMask | (1 << (digit / 2)),
                    oddMask, N);
            }
        }
    }
 
    // Return the answer
    return val;
}
 
// Function to find number of N-digit
// numbers which has equal count of
// distinct odd and even digits
static void countNDigitNumber(int N)
{
     
    // Initialize dp array with -1
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < (1 << 5); j++)
        {
            for(int k = 0; k < (1 << 5); k++)
            {
                dp[i, j, k] = -1;
            }
        }
    }
     
    // Function Call
    Console.Write(countOfNumbers(1, 0, 0, N));
}
 
 
// Driver Code
public static void Main()
{
    int N = 3;
    countNDigitNumber(N);
}
}
 
// This code is contributed by target_2.


输出:
135

时间复杂度: O(N *10 * 2 5 * 2 5 )
辅助空间: O(N * 2 5 * 2 5 )