📌  相关文章
📜  计算(A,B)对,以使A具有X,B具有Y个设置位,并且A + B = C

📅  最后修改于: 2021-04-17 12:02:22             🧑  作者: Mango

给定两个数字x,y,它表示设置的位数。还给出了数字C。任务是打印形成两个数字A和B的方式,以使A具有x个设置位,而B具有y个设置位,并且A + B =C。

例子

Input: X = 1, Y = 1, C = 3 
Output: 2 
So two possible ways are (A = 2 and B = 1) and (A = 1 and B = 2)

Input: X = 2, Y = 2, C = 20 
Output: 3 

方法:使用位掩码DP可以解决上述问题。

  1. 将大小为64 * 64 * 64 * 24-D DP数组初始化为10 ^ 18最多具有64个设置位,其中-1
  2. DP阵列的第一个状态存储从右向C遍历的位数。第二状态存储X中使用的置位位数,第三状态存储Y中使用的置位位数。第四状态是进位位,它是指我们执行加法运算时生成的进位。
  3. 复发将有4种可能性。我们从最右边的位开始。
  4. 如果C处的位位置为1,则有四种可能性在该索引处获得1。
    • 如果进位为0,则可以使用X中的1位和Y中的0位,反之亦然,下一步不产生任何进位。
    • 如果进位为1,则可以从每个位使用1个置位产生下一步的进位,否则我们不使用X和Y的任何置位产生不进位。
  5. 如果C处的位位置为0,则有四种可能性在该位位置获得0。
    • 如果进位为1,那么我们可以使用X中的1设置位和Y中的0位,反之亦然,这将为下一步生成1的进位。
    • 如果进位为0,则可以分别使用X和Y中的1和1,这将为下一步生成1的进位。我们也可以不使用设置位,这不会为下一步产生进位。
  6. 所有可能性的总和存储在dp [第三] [setb] [carry]中,以避免再次访问相同的状态。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
using namespace std;
  
// Initial DP array
int dp[64][64][64][2];
  
// Recursive function to generate
// all combinations of bits
int func(int third, int seta, int setb,
         int carry, int number)
{
  
    // if the state has already been visited
    if (dp[third][seta][setb][carry] != -1)
        return dp[third][seta][setb][carry];
  
    // find if C has no more set bits on left
    int shift = (number >> third);
  
    // if no set bits are left for C
    // and there are no set bits for A and B
    // and the carry is 0, then
    // this combination is possible
    if (shift == 0 and seta == 0 and setb == 0 and carry == 0)
        return 1;
  
    // if no set bits are left for C and
    // requirement of set bits for A and B have exceeded
    if (shift == 0 or seta < 0 or setb < 0)
        return 0;
  
    // Find if the bit is 1 or 0 at
    // third index to the left
    int mask = shift & 1;
  
    dp[third][seta][setb][carry] = 0;
  
    // carry = 1 and bit set = 1
    if ((mask) && carry) {
  
        // since carry is 1, and we need 1 at C's bit position
        // we can use 0 and 0
        // or 1 and 1 at A and B bit position
        dp[third][seta][setb][carry]
                += func(third + 1, seta, setb, 0, number)
                + func(third + 1, seta - 1, setb - 1, 1, number);
    }
  
    // carry = 0 and bit set = 1
    else if (mask && !carry) {
  
        // since carry is 0, and we need 1 at C's bit position
        // we can use 1 and 0
        // or 0 and 1 at A and B bit position
        dp[third][seta][setb][carry] 
                += func(third + 1, seta - 1, setb, 0, number)
                + func(third + 1, seta, setb - 1, 0, number);
    }
  
    // carry = 1 and bit set = 0
    else if (!mask && carry) {
  
        // since carry is 1, and we need 0 at C's bit position
        // we can use 1 and 0
        // or 0 and 1 at A and B bit position
        dp[third][seta][setb][carry] 
                  += func(third + 1, seta - 1, setb, 1, number)
                  + func(third + 1, seta, setb - 1, 1, number);
    }
  
    // carry = 0 and bit set = 0
    else if (!mask && !carry) {
  
        // since carry is 0, and we need 0 at C's bit position
        // we can use 0 and 0
        // or 1 and 1 at A and B bit position
        dp[third][seta][setb][carry] 
                  += func(third + 1, seta, setb, 0, number)
                  + func(third + 1, seta - 1, setb - 1, 1, number);
    }
  
    return dp[third][seta][setb][carry];
}
  
// Function to count ways
int possibleSwaps(int a, int b, int c)
{
  
    memset(dp, -1, sizeof(dp));
  
    // function call that returns the
    // answer
    int ans = func(0, a, b, 0, c);
  
    return ans;
}
  
// Driver Code
int main()
{
  
    int x = 2, y = 2, c = 20;
  
    cout << possibleSwaps(x, y, c);
  
    return 0;
}


Java
// Java implementation of the above approach 
import java.util.*;
class GfG { 
  
// Initial DP array 
static int dp[][][][] = new int[64][64][64][2]; 
  
// Recursive function to generate 
// all combinations of bits 
static int func(int third, int seta, int setb, 
                int carry, int number) 
{ 
  
    // if the state has already been visited 
    if (dp[third][seta][setb][carry] != -1) 
        return dp[third][seta][setb][carry]; 
  
    // find if C has no more set bits on left 
    int shift = (number >> third); 
  
    // if no set bits are left for C 
    // and there are no set bits for A and B 
    // and the carry is 0, then 
    // this combination is possible 
    if (shift == 0 && seta == 0 && setb == 0 && carry == 0) 
        return 1; 
  
    // if no set bits are left for C and 
    // requirement of set bits for A and B have exceeded 
    if (shift == 0 || seta < 0 || setb < 0) 
        return 0; 
  
    // Find if the bit is 1 or 0 at 
    // third index to the left 
    int mask = shift & 1; 
  
    dp[third][seta][setb][carry] = 0; 
  
    // carry = 1 and bit set = 1 
    if ((mask == 1) && carry == 1) { 
  
        // since carry is 1, and we need 1 at C's bit position 
        // we can use 0 and 0 
        // or 1 and 1 at A and B bit position 
        dp[third][seta][setb][carry] 
                            += func(third + 1, seta, setb, 0, number) 
                            + func(third + 1, seta - 1, setb - 1, 1, number); 
    } 
  
    // carry = 0 and bit set = 1 
    else if (mask == 1 && carry == 0) { 
  
        // since carry is 0, and we need 1 at C's bit position 
        // we can use 1 and 0 
        // or 0 and 1 at A and B bit position 
        dp[third][seta][setb][carry] 
                                    += func(third + 1, seta - 1, setb, 0, number) 
                                    + func(third + 1, seta, setb - 1, 0, number); 
    } 
  
    // carry = 1 and bit set = 0 
    else if (mask == 0 && carry == 1) { 
  
        // since carry is 1, and we need 0 at C's bit position 
        // we can use 1 and 0 
        // or 0 and 1 at A and B bit position 
        dp[third][seta][setb][carry] += func(third + 1, seta - 1, setb, 1, number) 
                                    + func(third + 1, seta, setb - 1, 1, number); 
    } 
  
    // carry = 0 and bit set = 0 
    else if (mask == 0 && carry == 0) { 
  
        // since carry is 0, and we need 0 at C's bit position 
        // we can use 0 and 0 
        // or 1 and 1 at A and B bit position 
        dp[third][seta][setb][carry] += func(third + 1, seta, setb, 0, number) 
                                    + func(third + 1, seta - 1, setb - 1, 1, number); 
    } 
  
    return dp[third][seta][setb][carry]; 
} 
  
// Function to count ways 
static int possibleSwaps(int a, int b, int c) 
{ 
    for(int q = 0; q < 64; q++)
    {
        for(int r = 0; r < 64; r++)
        {
            for(int p = 0; p < 64; p++)
            {
                for(int d = 0; d < 2; d++)
                {
                    dp[q][r][p][d] = -1;
                }
            }
        }
    }
      
  
    // function call that returns the 
    // answer 
    int ans = func(0, a, b, 0, c); 
  
    return ans; 
} 
  
// Driver Code 
public static void main(String[] args) 
{ 
  
    int x = 2, y = 2, c = 20; 
  
    System.out.println(possibleSwaps(x, y, c)); 
}
}


Python3
# Python3 implementation of the above approach 
  
# Initial DP array 
dp = [[[[-1, -1] for i in range(64)] 
                 for j in range(64)] 
                 for k in range(64)] 
  
# Recursive function to generate 
# all combinations of bits 
def func(third, seta, setb, carry, number): 
  
    # if the state has already been visited 
    if dp[third][seta][setb][carry] != -1:
        return dp[third][seta][setb][carry] 
  
    # find if C has no more set bits on left 
    shift = number >> third 
  
    # if no set bits are left for C 
    # and there are no set bits for A and B 
    # and the carry is 0, then 
    # this combination is possible 
    if (shift == 0 and seta == 0 and 
        setb == 0 and carry == 0): 
        return 1
  
    # if no set bits are left for C and 
    # requirement of set bits for A and B have exceeded 
    if (shift == 0 or seta < 0 or setb < 0):
        return 0
  
    # Find if the bit is 1 or 0 at 
    # third index to the left 
    mask = shift & 1
  
    dp[third][seta][setb][carry] = 0
  
    # carry = 1 and bit set = 1 
    if (mask) and carry: 
  
        # since carry is 1, and we need 1 at 
        # C's bit position we can use 0 and 0 
        # or 1 and 1 at A and B bit position 
        dp[third][seta][setb][carry] +=\
                func(third + 1, seta, setb, 0, number) + \
                func(third + 1, seta - 1, setb - 1, 1, number) 
      
    # carry = 0 and bit set = 1 
    elif mask and not carry: 
  
        # since carry is 0, and we need 1 at C's 
        # bit position we can use 1 and 0 
        # or 0 and 1 at A and B bit position 
        dp[third][seta][setb][carry] +=\
                func(third + 1, seta - 1, setb, 0, number) + \
                func(third + 1, seta, setb - 1, 0, number) 
      
    # carry = 1 and bit set = 0 
    elif not mask and carry: 
  
        # since carry is 1, and we need 0 at C's 
        # bit position we can use 1 and 0 
        # or 0 and 1 at A and B bit position 
        dp[third][seta][setb][carry] +=\
                func(third + 1, seta - 1, setb, 1, number) + \
                func(third + 1, seta, setb - 1, 1, number) 
      
    # carry = 0 and bit set = 0 
    elif not mask and not carry: 
  
        # since carry is 0, and we need 0 at C's 
        # bit position we can use 0 and 0 
        # or 1 and 1 at A and B bit position 
        dp[third][seta][setb][carry] += \
                func(third + 1, seta, setb, 0, number) + \
                func(third + 1, seta - 1, setb - 1, 1, number) 
      
    return dp[third][seta][setb][carry] 
  
# Function to count ways 
def possibleSwaps(a, b, c): 
  
    # function call that returns the answer 
    ans = func(0, a, b, 0, c) 
    return ans 
  
# Driver Code 
if __name__ == "__main__": 
  
    x, y, c = 2, 2, 20
    print(possibleSwaps(x, y, c)) 
  
# This code is contributed by Rituraj Jain


C#
// C# implementation of the above approach 
using System;
  
class GFG 
{ 
  
// Initial DP array 
static int [,,,]dp = new int[64, 64, 64, 2]; 
  
// Recursive function to generate 
// all combinations of bits 
static int func(int third, int seta, int setb, 
                int carry, int number) 
{ 
  
    // if the state has already been visited 
    if (third > -1 && seta > -1 &&
         setb > -1 && carry > -1)
        if(dp[third, seta, setb, carry] != -1)
            return dp[third, seta, setb, carry]; 
  
    // find if C has no more set bits on left 
    int shift = (number >> third); 
  
    // if no set bits are left for C 
    // and there are no set bits for A and B 
    // and the carry is 0, then 
    // this combination is possible 
    if (shift == 0 && seta == 0 &&  
         setb == 0 && carry == 0) 
        return 1; 
  
    // if no set bits are left for C and 
    // requirement of set bits for A and
    // B have exceeded 
    if (shift == 0 || seta < 0 || setb < 0) 
        return 0; 
  
    // Find if the bit is 1 or 0 at 
    // third index to the left 
    int mask = shift & 1; 
  
    dp[third, seta, setb, carry] = 0; 
  
    // carry = 1 and bit set = 1 
    if ((mask == 1) && carry == 1) 
    { 
  
        // since carry is 1, and we need 1 at 
        // C's bit position, we can use 0 and 0 
        // or 1 and 1 at A and B bit position 
        dp[third, seta, 
           setb, carry] += func(third + 1, seta, 
                                setb, 0, number) +
                           func(third + 1, seta - 1, 
                                setb - 1, 1, number); 
    } 
  
    // carry = 0 and bit set = 1 
    else if (mask == 1 && carry == 0)
    { 
  
        // since carry is 0, and we need 1 at 
        // C's bit position, we can use 1 and 0 
        // or 0 and 1 at A and B bit position 
        dp[third, seta, 
           setb, carry] += func(third + 1, seta - 1, 
                                  setb, 0, number) + 
                           func(third + 1, seta, 
                                setb - 1, 0, number); 
    } 
  
    // carry = 1 and bit set = 0 
    else if (mask == 0 && carry == 1) 
    { 
  
        // since carry is 1, and we need 0 at
        // C's bit position, we can use 1 and 0 
        // or 0 and 1 at A and B bit position 
        dp[third, seta, 
           setb, carry] += func(third + 1, seta - 1, 
                                setb, 1, number) + 
                           func(third + 1, seta, 
                                setb - 1, 1, number); 
    } 
  
    // carry = 0 and bit set = 0 
    else if (mask == 0 && carry == 0) 
    { 
  
        // since carry is 0, and we need 0 at 
        // C's bit position, we can use 0 and 0 
        // or 1 and 1 at A and B bit position 
        dp[third, seta, 
           setb, carry] += func(third + 1, seta, 
                                setb, 0, number) + 
                           func(third + 1, seta - 1, 
                                setb - 1, 1, number); 
    } 
    return dp[third, seta, setb, carry]; 
} 
  
// Function to count ways 
static int possibleSwaps(int a, int b, int c) 
{ 
    for(int q = 0; q < 64; q++)
    {
        for(int r = 0; r < 64; r++)
        {
            for(int p = 0; p < 64; p++)
            {
                for(int d = 0; d < 2; d++)
                {
                    dp[q, r, p, d] = -1;
                }
            }
        }
    }
      
    // function call that returns the 
    // answer 
    int ans = func(0, a, b, 0, c); 
  
    return ans; 
} 
  
// Driver Code 
public static void Main(String[] args) 
{ 
    int x = 2, y = 2, c = 20; 
  
    Console.WriteLine(possibleSwaps(x, y, c)); 
}
} 
  
// This code is contributed by Rajput-Ji


输出:
3