概率与期望

CF1523E

前面显然期望转换。

考虑最后不满足状态。

钦定i盏灯点亮,那就是 \(\binom{n}{i}\)

然后我要求不满足,那就是每两盏之间要有至少 \(k-1\) 盏,提前减去即可。

注意细节,要提前减去的灯数够用,否则 break,不然会爆 int

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i32 read() {
  i32 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1523E {
  bool _1;
  static const i32 N = 100005;
  static const i32 P = 1000000007;
  i32 n, k;
  i32 fac[N], inv[N];
  bool _2;
  i32 inc(i32 x, i32 y) { return (x + y) % P; }
  template<typename ...Args>
  i32 inc(i32 x, Args ...args) { return inc(x, inc(args...)); }
  i32 dec(i32 x, i32 y) { return (x + P - y) % P; }
  i32 mul(i32 x, i32 y) { return 1LL * x * y % P; }
  template<typename ...Args>
  i32 mul(i32 x, Args ...args) { return mul(x, mul(args...)); } 
  i32 qpow(i32 x, i32 y) {
    i32 ans = 1;
    for (; y; y >>= 1, x = mul(x, x))
      if (y & 1) ans = mul(ans, x);
    return ans;
  }
  void init(i32 n) {
    fac[0] = 1;
    for (i32 i = 1; i <= n; ++i) fac[i] = mul(fac[i - 1], i);
    inv[n] = qpow(fac[n], P - 2);
    for (i32 i = n - 1; i >= 0; --i) inv[i] = mul(inv[i + 1], i + 1);
    return void();
  }
  i32 binom(i32 n, i32 m) {
    if (n < m || m < 0) return 0;
    return mul(fac[n], inv[m], inv[n - m]);
  }
  i32 f(i32 n, i32 k, i32 i) { return mul(binom(n - (i - 1) * (k - 1), i), qpow(binom(n, i), P - 2)); }
  void solve() {
    n = read(), k = read();
    i32 ans = 1;
    for (i32 i = 1; i < n; ++i) {
      if ((i - 1) * (k - 1) > n) break;
      ans = inc(ans, f(n, k, i));
    }
    return fprintf(fout, "%d\n", ans), void();
  }
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    init(N - 1);
    i32 t = read();
    i64 Start_Time_Without_Read = clock();
    while (t--) solve();
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1523E::main(), 0; }

CF1737E

思考一个人怎么赢。

他必须得向左。

首先一定是吃掉左边连续的向右。

然后此时剩下一堆左的。

在我吃到他们前,他们一定先吃完了,所以是相当于我要吃掉前 \(i-1\) 个。

考虑我去吃的时候,左边重量是前 \(i-1\) 个的重量和减去我左边连续的向右的。

所以前面得有 \(n - \frac{i}{2} - 2\) 个向右的,再强制钦定我必须向左,所以要 \(2^{n - \frac{i}{2} - 1}\)

\(f_i\)\(i\) 胜利的概率。

然后是我后面不能赢,后面至少是 \(2i\) 开始的,所以是 \(1 - \sum_{j\geq2i}f_i\)

直接倒着做加上前缀\后缀和即可。

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i32 read() {
  i32 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1737E {
  bool _1;
  static const i32 N = 1000005;
  static const i32 P = 1000000007;
  i32 n, f[N], sum[N], fpow2[N];
  bool _2;
  i32 inc(i32 x, i32 y) { return (x + y) % P; }
  i32 dec(i32 x, i32 y) { return (x + P - y) % P; }
  i32 mul(i32 x, i32 y) { return 1LL * x * y % P; }
  i32 qpow(i32 x, i32 y) {
    i32 ans = 1;
    for (; y; y >>= 1, x = mul(x, x))
      if (y & 1) ans = mul(ans, x);
    return ans;
  }
  i32 sumf(i32 l, i32 r) {
    if (l > r) return 0;
    return sum[l] - sum[r + 1];
  }
  void solve() {
    n = read();
    sum[n + 1] = 0;
    f[n] = 1, sum[n] = 1;
    for (i32 i = n - 1; i >= 1; --i) {
      // i/2+1 ~ i
      i32 l = i + 1, r = std::min(2 * i - 1, n);
      f[i] = dec(sum[l], sum[r + 1]);
      sum[i] = inc(sum[i + 1], f[i]);
    }
    for (i32 i = 1; i <= n; ++i)
      fprintf(fout, "%d\n", mul(f[i], qpow(fpow2[n - i / 2 - 1], P - 2)));
    return void();
  }
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    fpow2[0] = 1;
    for (i32 i = 1; i < N; ++i)
      fpow2[i] = mul(fpow2[i - 1], 2);
    i32 t = read();
    i64 Start_Time_Without_Read = clock();
    while (t--) solve();
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1737E::main(), 0; }

CF1874C

由于拓扑,考虑从后往前做。

\(f_i\)\(i\)\(n\) 的答案。

每次显然选 f 值最大的更优。

预处理 \(dp_{i,j}\) 为出度为 \(i\) 的点,选到第 \(j\) 大的概率。

大概写一下, \(dp_{i,1} = \frac{1}{i}, dp_{i,2} = \frac{i-2}{i} \times \frac{1}{i-2}\)

然后转移很显然了, \(dp_{i,j} = dp_{i-2,j-2} \times \frac{j-2}{i} + dp_{i-2,j-1} \times \frac{i - j}{i}\)

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i32 read() {
  i32 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1874C {
  bool _1;
  static const i32 N = 5005;
  i32 n, m;
  double f[N][N], dp[N];
  std::vector<i32> e[N];
  void init(i32 n) {
    f[1][1] = 1, f[2][1] = 0.5;
    for (i32 i = 3; i <= n; ++i) {
      f[i][1] = 1.0 / i;
      for (i32 j = 2; j <= n; ++j)
        f[i][j] = 1.0 * (j - 2) / i * f[i - 2][j - 2] + 1.0 * (i - j) / i * f[i - 2][j - 1];
    }
    return void();
  }
  void solve() {
    n = read(), m = read();
    for (i32 i = 1; i <= n; ++i) e[i].clear();
    for (i32 i = 1; i <= m; ++i) {
      static i32 u, v;
      u = read(), v = read();
      e[u].eb(v);
    }
    dp[n] = 1;
    for (i32 i = n - 1; i >= 1; --i) {
      dp[i] = 0;
      std::sort(all(e[i]), [&](const i32 &x, const i32 &y) { return dp[x] > dp[y]; });
      for (i32 j = 0; j < size(e[i]); ++j) dp[i] += dp[e[i][j]] * f[size(e[i])][j + 1];
    }
    fprintf(fout, "%.9lf\n", dp[1]);
    return void();
  }
  bool _2;
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    init(N - 1);
    i32 t = read();
    i64 Start_Time_Without_Read = clock();
    while (t--) solve();
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1874C::main(), 0; }

CF1874D

考虑 \(f_i = 1 + \frac{a_i}{a_i + a_{i + 1}} \times f_{i - 1} + \frac{a_{i + 1}}{a_i + a_{i + 1}} \times f_{i + 1}\)

化简后, \(a_{i+1}(f_i-f_{i+1}) = a_i(f_{i-1}-f_{i})+a_i+a_{i+1}\)

差分一下,\(g_i = f_{i-1}-f_i,g_i = \frac{2 \sum_{j<i}a_j}{a_i} + 1\)

答案就是 \(\sum_i g_i\)

展开成为 \(2 * \sum_i \frac{1}{a_i} \sum_{j<i} a_j + n\)

\(dp_{i,j}\) 表示我考虑到第 \(i\) 位,和为 \(j\)

\(dp_{i+1,j+k} = dp_{i,j} + \frac{j}{k}\)

本来 \(O(n^3)\),由于显然 \(a_i\) 单调不减, \(k\) 的取值是类似调和级数,复杂度 \(O(n^2 \log n)\)

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i32 read() {
  i32 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1874D {
  bool _1;
  static const i32 N = 3005;
  i32 n, m;
  double dp[N][N];
  bool _2;
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    n = read(), m = read();
    i64 Start_Time_Without_Read = clock();
    for (i32 i = 0; i <= n; ++i)
      for (i32 j = 0; j <= m; ++j)
        dp[i][j] = 1e18;
    dp[0][0] = 0;
    for (i32 i = 0; i < n; ++i)
      for (i32 s = 0; s <= m; ++s)
        for (i32 j = 1; s + (n - i) * j <= m; ++j)
          chkmin(dp[i + 1][s + j], dp[i][s] + 1.0 * s / j);
    fprintf(fout, "%.9lf\n", 2 * dp[n][m] + n);
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1874D::main(), 0; }

CF1295F

有个显然的 dp,记 \(f_{i,j}\) 为考虑到第 \(i\) 位,\(a_i = j\) 的方案。

考虑直接离散,然后根据上面的改。

有个小技巧,把所有区间表示为左闭右开的形式,这样可以拆成很多单位区间。

然后套用上面的 dp,但是在一个单位区间也有可能不同,这时候枚举一个 \(k\),表示 \([k, i]\) 内的数都在这个单位区间,方案在乘上一个系数即可。

系数的话考虑我有 \(a_{j+1} - a_j\) 个位置,然后由于可以相等,就用插板法,\(\binom{a_{j+1}-a_j+1+(i-k)}{i-k}\)

由于算的是方案,还得除以总方案。

注意一下区间范围是 long long,组合数直接暴力求。

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i64 read() {
  i64 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1295F {
  bool _1;
  static const i32 N = 55;
  static const i32 P = 998244353;
  i32 n;
  i64 l[N], r[N], a[N * 2];
  i32 f[N][N * 2];
  bool _2;
  i32 inc(i32 x, i32 y) { return (x + y) % P; }
  i32 dec(i32 x, i32 y) { return (x + P - y) % P; }
  i32 mul(i32 x, i32 y) { return 1LL * x * y % P; }
  i32 qpow(i32 x, i32 y) {
    i32 ans = 1;
    for (; y; y >>= 1, x = mul(x, x))
      if (y & 1) ans = mul(ans, x);
    return ans;
  }
  i32 binom(i64 n, i32 m) {
    if (n < m || m < 0) return 0;
    i32 ans = 1;
    for (i64 i = n; i > n - m; --i) ans = mul(ans, i % P);
    for (i32 i = 1; i <= m; ++i) ans = mul(ans, qpow(i, P - 2));
    return ans;
  }
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    n = read();
    for (i32 i = 1; i <= n; ++i) {
      l[i] = read(), r[i] = read() + 1;
      a[i * 2 - 1] = l[i], a[i * 2] = r[i];
    }
    i64 Start_Time_Without_Read = clock();
    std::sort(a + 1, a + 2 * n + 1);
    i32 m = std::unique(a + 1, a + 2 * n + 1) - a - 1;
    for (i32 i = 1; i <= n; ++i) l[i] = std::lower_bound(a + 1, a + m + 1, l[i]) - a;
    for (i32 i = 1; i <= n; ++i) r[i] = std::lower_bound(a + 1, a + m + 1, r[i]) - a;
    f[0][m] = 1;
    for (i32 i = 1; i <= n; ++i)
      for (i32 j = 1; j < m; ++j)
        for (i32 k = i - 1; k >= 0; --k) {
          if (!(l[k + 1] <= j && j + 1 <= r[k + 1])) break;
          i32 now = 0;
          for (i32 p = j + 1; p <= m; ++p) now = inc(now, f[k][p]);
          now = mul(now, binom(a[j + 1] - a[j] - 1 + (i - k), i - k));
          f[i][j] = inc(f[i][j], now);
        }
    i32 ans = 0;
    for (i32 i = 1; i < m; ++i) ans = inc(ans, f[n][i]);
    for (i32 i = 1; i <= n; ++i) ans = mul(ans, qpow((a[r[i]] - a[l[i]]) % P, P - 2));
    fprintf(fout, "%d\n", ans);
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1295F::main(), 0; }

CF1842G

考虑组合意义。

相当于一条 1~\(n+1\) 的链,\(i\)\(i+1\)\(a_i\) 中走法,我可以随机放工具,得到工具可以多 \(v\) 种走法,工具随时使用。

直接 dp,考虑走到第 \(i\) 个点,有 \(j\) 个工具。

  1. 直接用 \(a_i\) 走, \(dp_{i+1,j}<-dp_{i,j}*a_i\)

  2. 使用拥有的工具, \(dp_{i+1,j}<-dp_{i,j}*j*v\)

  3. 新增工具,可以从 \([1,i]\) 中任意一点来, \(dp_{i+1,j+1}<-dp_{i,j}*(m-j)*(i+1)*v\)

最后除去总方案即可。

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i32 read() {
  i32 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1842G {
  bool _1;
  static const i32 N = 5005;
  static const i32 P = 1000000007;
  i32 n, m, v;
  i32 a[N];
  i32 dp[N][N];
  i32 fpown[N];
  bool _2;
  i32 inc(i32 x, i32 y) { return (x + y) % P; }
  template<typename ...Args>
  i32 inc(i32 x, Args ...args) { return inc(x, inc(args...)); }
  i32 dec(i32 x, i32 y) { return (x + P - y) % P; }
  i32 mul(i32 x, i32 y) { return 1LL * x * y % P; }
  template<typename ...Args>
  i32 mul(i32 x, Args ...args) { return mul(x, mul(args...)); } 
  i32 qpow(i32 x, i32 y) {
    i32 ans = 1;
    for (; y; y >>= 1, x = mul(x, x))
      if (y & 1) ans = mul(ans, x);
    return ans;
  }
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    n = read(), m = read(), v = read();
    for (i32 i = 1; i <= n; ++i) a[i] = read();
    i64 Start_Time_Without_Read = clock();
    fpown[0] = 1;
    for (i32 i = 1; i <= std::min(n, m); ++i) fpown[i] = mul(fpown[i - 1], n);
    dp[1][0] = 1;
    for (i32 i = 1; i <= n; ++i)
      for (i32 j = 0; j <= std::min(m, i); ++j) {
        dp[i + 1][j] = inc(dp[i + 1][j], mul(dp[i][j], a[i]));
        dp[i + 1][j] = inc(dp[i + 1][j], mul(dp[i][j], j, v));
        dp[i + 1][j + 1] = inc(dp[i + 1][j + 1], mul(dp[i][j], i, m - j, v));
      }
    i32 ans = 0;
    for (i32 i = 0; i <= std::min(n, m); ++i)
      ans = inc(ans, mul(dp[n + 1][i], qpow(fpown[i], P - 2)));
    fprintf(fout, "%d\n", ans);
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1842G::main(), 0; }

CF1842H

对每个 \(x_i\) 先减 \(0.5\),限制变成 \(\geq0\)\(\leq0\)

给每个 \(x_i\) 取绝对值,显然对于所有条件,我只需要考虑绝对值更大的数他的正负。

\(dp_S\) 为当前考虑集合 \(S\) 的数,是合法的方案书。

每次枚举一个加入的数,由于我们钦定从大到小加入,直接判一下它取正负是否符合条件加上方案即可。

由于钦定顺序,最后除总方案多除 \(n!\) 即可。

#pragma region
#include <bits/stdc++.h>
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define ep emplace
#define eb emplace_back
#define all(x) x.begin(), x.end()
FILE *fin, *fout, *ferr;
i32 read() {
  i32 t = 0, f = 0;
  char ch = fgetc(fin);
  for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
  for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
  return f ? -t : t;
}
template<typename T1, typename T2>
constexpr bool chkmax(T1 &a, T2 b) { return a > b ? false : (a = b, true); } 
template<typename T1, typename T2>
constexpr bool chkmin(T1 &a, T2 b) { return a > b ? (a = b, true) : false; } 
#pragma endregion
namespace Solution_Of_CF1842H {
  bool _1;
  static const i32 N = 20;
  static const i32 P = 998244353;
  i32 n, m;
  i32 a[N][2], f[1 << N];
  bool _2;
  i32 inc(i32 x, i32 y) { return (x + y) % P; }
  template<typename ...Args>
  i32 inc(i32 x, Args ...args) { return inc(x, inc(args...)); }
  i32 dec(i32 x, i32 y) { return (x + P - y) % P; }
  i32 mul(i32 x, i32 y) { return 1LL * x * y % P; }
  template<typename ...Args>
  i32 mul(i32 x, Args ...args) { return mul(x, mul(args...)); } 
  i32 qpow(i32 x, i32 y) {
    i32 ans = 1;
    for (; y; y >>= 1, x = mul(x, x))
      if (y & 1) ans = mul(ans, x);
    return ans;
  }
  void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    fprintf(ferr, "This code use %.2lf MB memory\n", 1.0 * (&_1 - &_2) / 1024 / 1024);
    n = read(), m = read();
    for (i32 i = 1; i <= m; ++i) {
      static i32 op, u, v;
      op = read();
      u = read() - 1, v = read() - 1;
      a[u][op] |= 1u << v, a[v][op] |= 1u << u;
    }
    i64 Start_Time_Without_Read = clock();
    f[0] = 1;
    for (i32 S = 0; S < (1 << n); ++S)
      for (i32 i = 0; i < n; ++i)
        if (S >> i & 1)
          for (i32 j = 0; j < 2; ++j)
            if (!(a[i][j ^ 1] & S))
              f[S] = inc(f[S], f[S ^ (1u << i)]);
    i32 ans = f[(1u << n) - 1];
    for (i32 i = 1; i <= n; ++i)
      ans = mul(ans, qpow(i, P - 2));
    ans = mul(ans, qpow(1 << n, P - 2));
    fprintf(fout, "%d\n", ans);
    i64 End_Time_Without_Read = clock();
    fprintf(ferr, "This code use %lld ms time\n", End_Time_Without_Read - Start_Time_Without_Read);
    return void();
  }
}
signed main() { return Solution_Of_CF1842H::main(), 0; }
posted @ 2023-10-23 20:06  xxcxu  阅读(7)  评论(0编辑  收藏  举报