给定两个数字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可以解决上述问题。
- 将大小为64 * 64 * 64 * 2的4-D DP数组初始化为10 ^ 18最多具有64个设置位,其中-1
- DP阵列的第一个状态存储从右向C遍历的位数。第二状态存储X中使用的置位位数,第三状态存储Y中使用的置位位数。第四状态是进位位,它是指我们执行加法运算时生成的进位。
- 复发将有4种可能性。我们从最右边的位开始。
- 如果C处的位位置为1,则有四种可能性在该索引处获得1。
- 如果进位为0,则可以使用X中的1位和Y中的0位,反之亦然,下一步不产生任何进位。
- 如果进位为1,则可以从每个位使用1个置位产生下一步的进位,否则我们不使用X和Y的任何置位产生不进位。
- 如果C处的位位置为0,则有四种可能性在该位位置获得0。
- 如果进位为1,那么我们可以使用X中的1设置位和Y中的0位,反之亦然,这将为下一步生成1的进位。
- 如果进位为0,则可以分别使用X和Y中的1和1,这将为下一步生成1的进位。我们也可以不使用设置位,这不会为下一步产生进位。
- 所有可能性的总和存储在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