Problem:
Score : 800 points

Problem Statement

Given are N pairwise distinct non-negative integers A_1,A_2,\ldots,A_N.
Find the number of ways to choose a set of between 1 and K numbers (inclusive) from the given numbers so that the following two conditions are satisfied:

The bitwise AND of the chosen numbers is S.

The bitwise OR of the chosen numbers is T.

Constraints

1 \leq N \leq 50

1 \leq K \leq N

0 \leq A_i < 2^{18}

0 \leq S < 2^{18}

0 \leq T < 2^{18}

A_i \neq A_j (1 \leq i < j \leq N)

Input

Input is given from Standard Input in the following format:

N K S T
A_1 A_2 ... A_N

Output

Print the answer.

Sample Input 1

3 3 0 3
1 2 3

Sample Output 1

2

The conditions are satisfied when we choose \{1,2\} or \{1,2,3\}.

Sample Input 2

5 3 1 7
3 4 9 1 5

Sample Output 2

2

Sample Input 3

5 4 0 15
3 4 9 1 5

Sample Output 3

3

Solution in C# (Mono-csc 3.5.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;

namespace AtCoder {
    class ORand {
        static int N, K, S, T;
        static List<int> A;
        static List<long> zeroMasks;

        static long[] waysToChoose;

        static long ans;

        static void Recurse(int pos, int masksCnt, long curMask) {
            if (curMask == 0) {
                return;
            }

            if (pos == zeroMasks.Count) {
                int bitCnt = 0;
                while (curMask > 0) {
                    bitCnt++;
                    curMask &= curMask - 1;
                }

                if (masksCnt % 2 == 0) {
                    ans += waysToChoose[bitCnt];
                } else {
                    ans -= waysToChoose[bitCnt];
                }

                return;
            }

            Recurse(pos + 1, masksCnt, curMask);
            Recurse(pos + 1, masksCnt + 1, curMask & zeroMasks[pos]);
            Recurse(pos + 1, masksCnt + 1, curMask & ((1L << A.Count) - 1 - zeroMasks[pos]));
        }

        public static void Main(string[] args) {
            var parts = Console.ReadLine().Split(' ');
            N = int.Parse(parts[0]);
            K = int.Parse(parts[1]);
            S = int.Parse(parts[2]);
            T = int.Parse(parts[3]);
            A = new List<int>();
            parts = Console.ReadLine().Split(' ');
            for (int i = 0; i < N; i++) {
                A.Add(int.Parse(parts[i]));
            }

            for (int b = 0; b < 18; b++) {
                int s = (S & (1 << b)) != 0 ? 1 : 0;
                int t = (T & (1 << b)) != 0 ? 1 : 0;

                if (s == 1 && t == 0) {
                    Console.WriteLine(0);
                    return;
                }

                if (s == t) {
                    var filtered = new List<int>();
                    foreach (var num in A) {
                        var n = (num & (1 << b)) != 0 ? 1 : 0;
                        if (n == s) {
                            filtered.Add(num);
                        }
                    }

                    A = filtered;
                    continue;
                }
            }

            zeroMasks = new List<long>();

            for (int b = 0; b < 18; b++) {
                int s = (S & (1 << b)) != 0 ? 1 : 0;
                int t = (T & (1 << b)) != 0 ? 1 : 0;

                if (s == 0 && t == 1) {
                    long mask = 0;
                    for (int i = 0; i < A.Count; i++) {
                        var n = (A[i] & (1 << b)) != 0 ? 1 : 0;
                        if (n == 0) {
                            mask |= (1L << i);
                        }
                    }
                    zeroMasks.Add(mask);
                }
            }

            N = A.Count;

            long[][] C = new long[N+1][];
            for (int i = 0; i <= N; i++) {
                C[i] = new long[N+1];
                C[i][0] = 1; C[i][i] = 1;
                for (int j = 1; j < i; j++) {
                    C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
                }
            }

            waysToChoose = new long[N+1];
            for (int i = 0; i <= N; i++) {
                for (int j = 1; j <= K && j <= i; j++) {
                    waysToChoose[i] += C[i][j];
                }
            }

            Recurse(0, 0, (1L << A.Count) - 1);

            Console.WriteLine(ans);
        }
    }
}