# count pairs ( a , b ) such that a has x and b has y number of set bits and a + b = c | initial dp array ; recursive function to generate all combinations of bits ; if the state has already been visited ; find if c has no more set bits on left ; 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 no set bits are left for c and requirement of set bits for a and b have exceeded ; find if the bit is 1 or 0 at third index to the left ; carry = 1 and bit set = 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 ; carry = 0 and bit set = 1 ; 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 ; carry = 1 and bit set = 0 ; 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 ; carry = 0 and bit set = 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 ; function to count ways ; function call that returns the answer ; 

dp = [[[[-1, -1]for i in range(64)]for j in range(64)]for k in range(64)]


def func(third, seta, setb, carry, number):
    if dp[third][seta][setb][carry] != -1:
        return dp[third][seta][setb][carry]
    shift = number >> third
    if (shift == 0 and seta == 0 and setb == 0 and carry == 0):
        return 1
    if (shift == 0 or seta < 0 or setb < 0):
        return 0
    mask = shift & 1
    dp[third][seta][setb][carry] = 0
    if (mask) and carry:
        dp[third][seta][setb][carry] += func(third + 1,
                                             seta,
                                             setb,
                                             0,
                                             number) + func(third + 1,
                                                            seta - 1,
                                                            setb - 1,
                                                            1,
                                                            number)
    elif mask and not carry:
        dp[third][seta][setb][carry] += func(third + 1,
                                             seta - 1,
                                             setb,
                                             0,
                                             number) + func(third + 1,
                                                            seta,
                                                            setb - 1,
                                                            0,
                                                            number)
    elif not mask and carry:
        dp[third][seta][setb][carry] += func(third + 1,
                                             seta - 1,
                                             setb,
                                             1,
                                             number) + func(third + 1,
                                                            seta,
                                                            setb - 1,
                                                            1,
                                                            number)
    elif not mask and not carry:
        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]


def possibleSwaps(a, b, c):
    ans = func(0, a, b, 0, c)
    return ans


if __name__ == "__main__":
    x, y, c = 2, 2, 20
    print(possibleSwaps(x, y, c))

# Expected output:
3