Problem p02649 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <bitset>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll(c, d)));
#define re(c, b) for (ll c = 0; c < b; c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;

void comb(vector<vector<long long int>> &v) {
  for (int i = 0; i < v.size(); i++) {
    v[i][0] = 1;
    v[i][i] = 1;
  }
  for (int k = 1; k < v.size(); k++) {
    for (int j = 1; j < k; j++) {
      v[k][j] = (v[k - 1][j - 1] + v[k - 1][j]);
    }
  }
}
vector<vector<long long int>> V(51, vector<long long int>(51, 0));

int main(int argc, char const *argv[]) {
  comb(V);
  ll n, k, s, t;
  std::cin >> n >> k >> s >> t;
  vll a;
  for (int i = 0; i < n; i++) {
    ll tmp;
    scanf("%lld", &tmp);
    if ((t | tmp) != t)
      continue;
    if ((s & tmp) != s)
      continue;
    a.push_back(tmp);
  }

  n = a.size();
  k = min(k, n);
  ll ans = 0;
  for (int i = 0; i < n; i++) {
    // iを確定
    // 全てのbitに「残りの要素全てが1だとダメ」(and) ,
    // 「残りの要素全てが0だとダメ」(or)のどちらかが科される
    vll c(1 << 18, 0); // k個以下取り、bitの条件に引っかかってダメな場合の数
    for (int b = 1; b < (1 << 18); b++) {
      bool g = true;
      for (int j = 0; j < 18; j++) {
        if (((b >> j) & 1) == 0)
          continue;
        if (((t >> j) & 1) == 0 && ((s >> j) & 1) == 1) {
          std::cout << 0 << '\\n';
          exit(0);
        }
        if (((t >> j) & 1) == ((s >> j) & 1)) {
          g = false;
          break;
        }
      }

      if (!g)
        c[b] = 0;
      else {
        ll cnt = 0;
        // 全ての条件を満たさないものがいくつあるか
        //  mask b について、a[i]とa[j]のmaskの位置のbitが等しい
        //  (!(a[i]^a[j]))&b == b
        for (int j = i + 1; j < n; j++) {
          ll xo = (a[i] ^ a[j]);
          if (((~xo) & b) == b)
            cnt++;
        }
        for (int j = 0; j <= min(k - 1, cnt); j++)
          c[b] += V[cnt][j];
      }
    }

    ll num = n - i - 1;
    ll all_pat = 0;
    for (int j = 0; j <= min(k - 1, num); j++)
      all_pat += V[num][j];

    // k個以下取って、どれかの条件に引っかかってダメな場合
    // 包除原理(奇数bit立っているなら加算、偶数なら減算)
    ll bad = 0;
    for (int b = 1; b < (1 << 18); b++) {
      if (__builtin_popcount(b) % 2)
        bad += c[b];
      else
        bad -= c[b];
    }
    // if(i==0) std::cout << c[1] << " " << c[2] << " " << c[3] << '\\n';
    // k個以下取って可能な場合　= all_pat - どれかでダメ
    ans += all_pat - bad;
  }
  std::cout << ans << '\\n';
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll(c, d)));
#define re(c, b) for (ll c = 0; c < b; c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;

void comb(vector<vector<long long int>> &v) {
  for (int i = 0; i < v.size(); i++) {
    v[i][0] = 1;
    v[i][i] = 1;
  }
  for (int k = 1; k < v.size(); k++) {
    for (int j = 1; j < k; j++) {
      v[k][j] = (v[k - 1][j - 1] + v[k - 1][j]);
    }
  }
}
vector<vector<long long int>> V(51, vector<long long int>(51, 0));

int main(int argc, char const *argv[]) {
  comb(V);
  ll n, k, s, t;
  std::cin >> n >> k >> s >> t;
  vll a;
  for (int i = 0; i < n; i++) {
    ll tmp;
    scanf("%lld", &tmp);
    if ((t | tmp) != t)
      continue;
    if ((s & tmp) != s)
      continue;
    a.push_back(tmp);
  }

  n = a.size();
  k = min(k, n);
  ll ans = 0;
  for (int i = 0; i < n; i++) {
    // iを確定
    // 全てのbitに「残りの要素全てが1だとダメ」(and) ,
    // 「残りの要素全てが0だとダメ」(or)のどちらかが科される
    vll c(1 << 18, 0); // k個以下取り、bitの条件に引っかかってダメな場合の数

    for (int b = 1; b < (1 << 18); b++) {
      ll cnt = 0;
      for (int j = i + 1; j < n; j++) {
        bool f = true;

        for (int p = 0; p < 18; p++) {
          if (((b >> p) & 1) == 0)
            continue;
          if (((t >> p) & 1) == ((s >> p) & 1)) {
            f = false;
            break;
          }
          if (((t >> p) & 1) == 0 && ((s >> p) & 1) == 1)
            continue;

          if (((a[i] >> p) & 1) != ((a[j] >> p) & 1)) {
            f = false;
            break;
          }
        }
        if (f)
          cnt++;
      }
      // 全体
      for (int j = 0; j <= (min(cnt, k - 1)); j++)
        c[b] += V[cnt][j];
    }
    ll num = n - i - 1;
    ll all_pat = 0;
    for (int j = 0; j <= min(k - 1, num); j++)
      all_pat += V[num][j];

    // k個以下取って、どれかの条件に引っかかってダメな場合
    // 包除原理(奇数bit立っているなら加算、偶数なら減算)
    ll bad = 0;
    for (int b = 1; b < (1 << 18); b++) {
      if (__builtin_popcount(b) % 2)
        bad += c[b];
      else
        bad -= c[b];
    }
    // k個以下取って可能な場合　= all_pat - どれかでダメ
    ans += all_pat - bad;
  }
  std::cout << ans << '\\n';
  return 0;
}