Submission #841086

#TimeUsernameProblemLanguageResultExecution timeMemory
841086peijarAmusement Park (CEOI19_amusementpark)C++17
42 / 100
412 ms1048576 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;

string to_string(string s) { return s; }
template <typename T> string to_string(T v) {
  bool first = true;
  string res = "[";
  for (const auto &x : v) {
    if (!first)
      res += ", ";
    first = false;
    res += to_string(x);
  }
  res += "]";
  return res;
}

void dbg_out() { cout << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
  cout << ' ' << to_string(H);
  dbg_out(T...);
}

#ifdef DEBUG
#define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif

template <const int32_t MOD> struct ModInt {
  int32_t x;
  ModInt() : x(0) {}
  ModInt(long long u) : x(u % MOD) {
    if (x < 0)
      x += MOD;
  }
  friend bool operator==(const ModInt &a, const ModInt &b) {
    return a.x == b.x;
  }
  friend bool operator!=(const ModInt &a, const ModInt &b) {
    return a.x != b.x;
  }
  friend bool operator<(const ModInt &a, const ModInt &b) { return a.x < b.x; }
  friend bool operator>(const ModInt &a, const ModInt &b) { return a.x > b.x; }
  friend bool operator<=(const ModInt &a, const ModInt &b) {
    return a.x <= b.x;
  }
  friend bool operator>=(const ModInt &a, const ModInt &b) {
    return a.x >= b.x;
  }
  static ModInt sign(long long k) {
    return ((k & 1) ? ModInt(MOD - 1) : ModInt(1));
  }

  ModInt &operator+=(const ModInt &m) {
    x += m.x;
    if (x >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator-=(const ModInt &m) {
    x -= m.x;
    if (x < 0LL)
      x += MOD;
    return *this;
  }
  ModInt &operator*=(const ModInt &m) {
    x = (1LL * x * m.x) % MOD;
    return *this;
  }

  friend ModInt operator-(const ModInt &a) {
    ModInt res(a);
    if (res.x)
      res.x = MOD - res.x;
    return res;
  }
  friend ModInt operator+(const ModInt &a, const ModInt &b) {
    return ModInt(a) += ModInt(b);
  }
  friend ModInt operator-(const ModInt &a, const ModInt &b) {
    return ModInt(a) -= ModInt(b);
  }
  friend ModInt operator*(const ModInt &a, const ModInt &b) {
    return ModInt(a) *= ModInt(b);
  }

  static long long fp(long long u, long long k) {
    long long res = 1LL;
    while (k > 0LL) {
      if (k & 1LL)
        res = (res * u) % MOD;
      u = (u * u) % MOD;
      k /= 2LL;
    }
    return res;
  }

  static constexpr int mod() { return MOD; }

  ModInt fastpow(long long k) { return ModInt(fp(x, k)); }
  ModInt inv() {
    assert(x);
    return ModInt(fp(x, MOD - 2));
  }
  ModInt &operator/=(const ModInt &m) { return *this *= ModInt(m).inv(); }
  friend ModInt operator/(const ModInt &a, const ModInt &b) {
    return ModInt(a) *= ModInt(b).inv();
  }

  friend ostream &operator<<(ostream &out, const ModInt &a) {
    return out << a.x;
  }
  friend istream &operator>>(istream &in, ModInt &a) { return in >> a.x; }
  friend string to_string(ModInt u) { return to_string(u.x); }
};

// const int MOD = 1e9 + 7;
const int MOD = 998244353;
using Mint = ModInt<MOD>;

signed main(void) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);

  int n, m;
  cin >> n >> m;
  vector<set<int>> adj(n);
  vector<int> bitAdj(n);
  for (int i = 0; i < m; ++i) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    adj[u].insert(v);
    bitAdj[u] |= 1 << v;
    bitAdj[v] |= 1 << u;
  }

  auto toVector = [&](int msk) {
    vector<int> ret;
    for (int i = 0; i < n; ++i)
      if ((1 << i) & msk)
        ret.push_back(i + 1);
    return ret;
  };

  vector<vector<Mint>> dpBack(1 << n, vector<Mint>(1 << n));
  vector<vector<Mint>> dpForward(1 << n, vector<Mint>(1 << n));
  dpBack[0][0] = 1;
  for (int added = 0; added < (1 << n); ++added) {
    int complement = (1 << n) - 1 - added;
    int bad = complement;
    while (true) {
      for (int nxt = 0; nxt < n; ++nxt)
        if (!((1 << nxt) & added) and !((1 << nxt) & bad)) {
          int nxtBad = bad & (bad ^ bitAdj[nxt]);
          for (int u = 0; u < nxt; ++u)
            if (!((1 << u) & added))
              if (!((1 << u) & bitAdj[nxt]))
                nxtBad |= 1 << u;
          dpBack[added ^ (1 << nxt)][nxtBad] += dpBack[added][bad];
        }
      if (!bad)
        break;
      bad = (bad - 1) & complement;
    }
  }

  dpForward[(1 << n) - 1][0] = 1;
  for (int added = (1 << n) - 2; added >= 0; --added) {
    int complement = (1 << n) - 1 - added;
    int bad = complement;
    while (true) {
      for (int nxt = 0; nxt < n; ++nxt)
        if (!((1 << nxt) & added) and !((1 << nxt) & bad)) {
          int nxtBad = bad & (bad ^ bitAdj[nxt]);
          for (int u = 0; u < nxt; ++u)
            if (!((1 << u) & added))
              if (!((1 << u) & bitAdj[nxt]))
                nxtBad |= 1 << u;
          dpForward[added][bad] += dpForward[added ^ (1 << nxt)][nxtBad];
        }
      if (!bad)
        break;
      bad = (bad - 1) & complement;
    }
  }
  Mint sol = 0;
  for (int added = 0; added < (1 << n); ++added) {
    int complement = (1 << n) - 1 - added;
    int bad = complement;
    while (true) {
      for (int nxt = 0; nxt < n; ++nxt)
        if (!((1 << nxt) & added) and !((1 << nxt) & bad)) {
          int nxtBad = bad & (bad ^ bitAdj[nxt]);
          for (int u = 0; u < nxt; ++u)
            if (!((1 << u) & added))
              if (!((1 << u) & bitAdj[nxt]))
                nxtBad |= 1 << u;
          Mint cnt = dpForward[added ^ (1 << nxt)][nxtBad] * dpBack[added][bad];
          int cntFlip = 0;
          for (int i = 0; i < n; ++i)
            if ((1 << i) & added)
              if (adj[nxt].count(i))
                cntFlip++;
          sol += cnt * cntFlip;
        }
      if (!bad)
        break;
      bad = (bad - 1) & complement;
    }
  }

  Mint sumCost = 0;
  for (int msk = 1; msk < (1 << n); ++msk)
    for (int der = 0; der < n; ++der)
      if ((1 << der) & msk) {
        for (int nxt = 0; nxt < n; ++nxt)
          if (!((1 << nxt) & msk)) {
            if (nxt < der and !adj[der].count(nxt) and !adj[nxt].count(der))
              continue;
            Mint cnt = dpForward[nxt][msk | (1 << nxt)] * dpBack[der][msk];
            int toFlip = 0;
            for (int u = 0; u < n; ++u)
              if ((1 << u) & msk)
                if (adj[nxt].count(u))
                  toFlip++;
            sumCost += toFlip * cnt;
          }
      }

  cout << sol << endl;
}

Compilation message (stderr)

amusementpark.cpp: In function 'int main()':
amusementpark.cpp:140:8: warning: variable 'toVector' set but not used [-Wunused-but-set-variable]
  140 |   auto toVector = [&](int msk) {
      |        ^~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...