• UOJ Round #12


    A

    结论:答案是 YES 当且仅当对于任意一个数,(A) 中比它小且在它前面的数在 (B) 中也在它前面。

    证明:必要性显然,充分性考虑直接把 (A) 中的数从前往后挪到 (B) 中对应的位置,则挪不动时一定与结论矛盾。

    那么直接三维数点即可,也可以改变枚举顺序后变成二维数点。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    const int MAXN = 100000 + 5;
    
    struct BinaryIndexedTree {
      int a[MAXN], n;
    
    #define lowbit(x) ((x) & -(x))
      void modify(int i, int x) {
        for (; i <= n; i += lowbit(i)) {
          a[i] += x;
        }
      }
    
      int query(int i) {
        int ret = 0;
        for (; i; i -= lowbit(i)) {
          ret += a[i];
        }
        return ret;
      }
    } bit;
    
    int a[MAXN], b[MAXN], p[MAXN], q[MAXN], ans[MAXN];
    
    void solve(int l, int r) {
      if (l == r) {
        return;
      }
      int mid = (l + r) >> 1, len = r - l + 1;
      solve(l, mid);
      static int tp[MAXN];
      For(i, l, r) {
        tp[i - l + 1] = i;
      }
      std::sort(tp + 1, tp + len + 1, [&](int a, int b) {
        return p[a] < p[b];
      });
      For(i, 1, len) {
        if (tp[i] <= mid) {
          bit.modify(q[tp[i]], 1);
        } else {
          ans[tp[i]] += bit.query(q[tp[i]]);
        }
      }
      For(i, l, mid) {
        bit.modify(q[i], -1);
      }
      solve(mid + 1, r);
    }
    
    int main() {
      int n;
      scanf("%d", &n);
      For(i, 1, n) {
        scanf("%d", &a[i]);
        p[a[i]] = i;
      }
      For(i, 1, n) {
        scanf("%d", &b[i]);
        q[b[i]] = i;
      }
      bit.n = n;
      solve(1, n);
      For(i, 1, n) {
        if (bit.query(p[i]) > ans[i]) {
          puts("NO");
          exit(0);
        }
        bit.modify(p[i], 1);
      }
      puts("YES");
      return 0;
    }
    

    B

    原图一定是竞赛图,则缩点之后是一条链,答案的期望相当于所有连通块满足“所有与这个连通块相连的边都是从这个连通块连出“的概率之和。

    发现同一个大小的连通块的答案可以一起算(只与特殊边有关),考虑状压 DP。

    考虑只保留特殊边形成的连通块,则每个连通块至多有 (m + 1) 个点,枚举这些点中哪些点在连通块内,贡献可以直接计算,合并连通块做个背包即可。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    namespace Math {
    const int MOD = 998244353;
    
    IL int add(int a, int b) {
      a += b;
      return a >= MOD ? a - MOD : a;
    }
    
    template <class ...Args>
    IL int add(int a, const Args &...args) {
      a += add(args...);
      return a >= MOD ? a - MOD : a;
    }
    
    IL int sub(int a, int b) {
      a -= b;
      return a < 0 ? a + MOD : a;
    }
    
    IL int mul(int a, int b) {
      return (LL)a * b % MOD;
    }
    
    template <class ...Args>
    IL int mul(int a, const Args &...args) {
      return (LL)a * mul(args...) % MOD;
    }
    
    IL int quickPow(int a, int p) {
      int ret = 1;
      for (; p; p >>= 1, a = mul(a, a)) {
        if (p & 1) {
          ret = mul(ret, a);
        }
      }
      return ret;
    }
    }
    
    using namespace Math;
    
    const int MAXN = 40 + 5, MAXM = 20 + 5, MASK = 1 << 20;
    
    using Pair = std::pair<int, int>;
    
    int f[MAXN], g[MAXN], to[MAXN], G[MAXN][MAXN], n, m, cnt;
    Pair eg[MAXM];
    bool vis[MAXN];
    
    void DFS(int u) {
      OK;
      to[u] = cnt ++;
      vis[u] = 1;
      For(i, 1, n) {
        if (~G[u][i] && !vis[i]) {
          DFS(i);
        }
      }
    }
    
    int main() {
      memset(G, -1, sizeof G);
      scanf("%d%d", &n, &m);
      int p = quickPow(10000, MOD - 2);
      For(i, 1, m) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        eg[i] = {u, v};
        G[u][v] = mul(w, p), G[v][u] = mul(10000 - w, p);
      }
      f[0] = 1;
      int cur = 0;
      For(i, 1, n) {
        if (!vis[i]) {
          memset(to, -1, sizeof to);
          memset(g, 0, sizeof g);
          cnt = 0;
          DFS(i);
          FOR(S, 0, 1 << cnt) {
            int w = __builtin_popcount(S), c = 1;
            For(j, 1, m) {
              int x = eg[j].first, y = eg[j].second, a = to[x], b = to[y];
              if (!~a || !~b) {
                continue;
              }
              if (((S >> a) & 1) && ((~S >> b) & 1)) {
                c = mul(c, add(G[x][y], G[x][y]));
              } else if (((~S >> a) & 1) && ((S >> b) & 1)) {
                c = mul(c, add(G[y][x], G[y][x]));
              }
            }
            g[w] = add(g[w], c);
          }
          cur += cnt;
          Rep(j, cur, 1) {
            For(k, 1, mymin(j, cnt)) {
              f[j] = add(f[j], mul(f[j - k], g[k]));
            }
          }
        }
      }
      int ans = 0;
      For(i, 1, n) {
        ans = add(ans, mul(f[i], quickPow((MOD + 1) / 2, i * (n - i))));
      }
      printf("%d
    ", mul(ans, quickPow(10000, n * (n - 1))));
      return 0;
    }
    

    C

    每一个时刻每个位置的值一定可以表示成 (frac{ax+b}{cx+d}),即 (p+frac{q}{x+r}) 的形式,其中除了 (x) 外都是常数。

    那么稍微化一下就是多点求值了。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-10, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((x).size())
    
    namespace Math {
    const int MOD = 998244353;
    
    IL int add(int a, int b) {
      a += b;
      return a >= MOD ? a - MOD : a;
    }
    
    template <class ...Args>
    IL int add(int a, const Args &...args) {
      a += add(args...);
      return a >= MOD ? a - MOD : a;
    }
    
    IL int sub(int a, int b) {
      a -= b;
      return a < 0 ? a + MOD : a;
    }
    
    IL int mul(int a, int b) {
      return (LL)a * b % MOD;
    }
    
    template <class ...Args>
    IL int mul(int a, const Args &...args) {
      return (LL)a * mul(args...) % MOD;
    }
    
    IL int quickPow(int a, int p) {
      int ret = 1;
      for (; p; p >>= 1, a = mul(a, a)) {
        if (p & 1) {
          ret = mul(ret, a);
        }
      }
      return ret;
    }
    }
    
    using namespace Math;
    
    const int MAXN = 100000 + 5, LOG = 19, G = 3, G_inv = 332748118, INV_2 = 499122177;
    
    namespace Poly {
    int pos[1 << LOG], root[1 << LOG], root_inv[1 << LOG], len;
    
    IL void init(int n) {
      for (; 1 << len < n; ++ len);
      FOR(i, 0, 1 << len) {
        pos[i] = (pos[i >> 1] >> 1) | ((i & 1) << (len - 1));
      }
      int w = quickPow(G, (MOD - 1) >> len);
      root[0] = 1;
      FOR(i, 1, 1 << len) {
        root[i] = mul(root[i - 1], w);
      }
      w = quickPow(G_inv, (MOD - 1) >> len);
      root_inv[0] = 1;
      FOR(i, 1, 1 << len) {
        root_inv[i] = mul(root_inv[i - 1], w);
      }
    }
    
    IL void NTT(int *a, int n, int *root) {
      int shift = __builtin_ctz((1 << len) / n);
      FOR(i, 0, n) {
        if (i > pos[i] >> shift) {
          std::swap(a[i], a[pos[i] >> shift]);
        }
      }
      for (int i = 2; i <= n; i <<= 1) {
        int k = i >> 1;
        shift = __builtin_ctz((1 << len) / i);
        for (int *p = a; p != a + n; p += i) {
          FOR(j, 0, k) {
            int temp = mul(p[j + k], root[j << shift]);
            p[j + k] = sub(p[j], temp);
            p[j] = add(p[j], temp);
          }
        }
      }
    }
    
    IL void DFT(int *a, int n) {
      NTT(a, n, root);
    }
    
    IL void IDFT(int *a, int n) {
      NTT(a, n, root_inv);
      int inv_n = quickPow(n, MOD - 2);
      FOR(i, 0, n) {
        a[i] = mul(a[i], inv_n);
      }
    }
    
    IL void multiply(int *a, int n, int *b, int m, int *ret) {
      int len = 0;
      for (; 1 << len < n + m; ++ len);
      static int x[1 << LOG], y[1 << LOG];
      std::copy(a, a + n, x);
      memset(x + n, 0, ((1 << len) - n) * sizeof (int));
      std::copy(b, b + m, y);
      memset(y + m, 0, ((1 << len) - m) * sizeof (int));
      memset(ret, 0, (1 << len) * sizeof (int));
      DFT(x, 1 << len);
      DFT(y, 1 << len);
      FOR(i, 0, 1 << len) {
        ret[i] = mul(x[i], y[i]);
      }
      IDFT(ret, 1 << len);
      memset(ret + n + m - 1, 0, ((1 << len) - n - m + 1) * sizeof (int));
    }
    
    void inverse(int *f, int *g, int t) {
      if (t == 1) {
        g[0] = quickPow(f[0], MOD - 2);
        return;
      }
      inverse(f, g, (t + 1) >> 1);
      int len = 0;
      for (; 1 << len < t << 1; ++ len);
      static int temp[1 << LOG];
      std::copy(f, f + t, temp);
      memset(temp + t, 0, ((1 << len) - t) * sizeof (int));
      DFT(temp, 1 << len);
      DFT(g, 1 << len);
      FOR(i, 0, 1 << len) {
        g[i] = mul(g[i], sub(2, mul(temp[i], g[i])));
      }
      IDFT(g, 1 << len);
      memset(g + t, 0, ((1 << len) - t) * sizeof (int));
    }
    
    IL void reverse(int *f, int n) {
      std::reverse(f, f + n);
    }
    
    IL void inc(int *f, int *g, int n, int *ret) {
      FOR(i, 0, n) {
        ret[i] = add(f[i], g[i]);
      }
    }
    
    IL void dec(int *f, int *g, int n, int *ret) {
      FOR(i, 0, n) {
        ret[i] = sub(f[i], g[i]);
      }
    }
    
    IL void divide(int *f, int n, int *g, int m, int *q, int *r) {
      if (n < m) {
        std::copy(f, f + n, r);
        return;
      }
      reverse(f, n), reverse(g, m);
      int len = 0;
      for (; 1 << len < mymax((n - m + 1) << 1, n + 1); ++ len);
      static int temp1[1 << LOG], temp2[1 << LOG];
      memset(temp1, 0, (1 << len) * sizeof (int));
      memset(temp2, 0, (1 << len) * sizeof (int));
      std::copy(g, g + m, temp1);
      inverse(temp1, temp2, n - m + 1);
      multiply(f, n - m + 1, temp2, n - m + 1, q);
      reverse(q, n - m + 1);
      reverse(f, n), reverse(g, m);
      multiply(g, m, q, n - m + 1, temp2);
      dec(f, temp2, m - 1, r);
    }
    
    int pre_work[LOG][MAXN * 8];
    
    void decoNTT(int *a, int level, int l, int r) {
      if (l + 1 >= r) {
        pre_work[level][l << 1] = sub(0, a[l]);
        pre_work[level][l << 1 | 1] = 1;
        return;
      }
      int mid = (l + r) >> 1;
      decoNTT(a, level + 1, l, mid);
      decoNTT(a, level + 1, mid, r);
      static int temp[1 << LOG];
      multiply(pre_work[level + 1] + (l << 1), mid - l + 1, pre_work[level + 1] + (mid << 1), r - mid + 1, temp);
      std::copy(temp, temp + r - l + 1, pre_work[level] + (l << 1));
    }
    
    int ret_eval[LOG][1 << LOG];
    
    void getEvaluation(int *f, int *g, int level, int l, int r, int len, int n) {
      static int temp[1 << LOG];
      int p = r - l;
      divide(f, len, pre_work[level] + (l << 1), p + 1, temp, ret_eval[level] + l);
      if (l + 1 >= r) {
        g[l] = ret_eval[level][l];
        return;
      }
      int mid = (l + r) >> 1;
      getEvaluation(ret_eval[level] + l, g, level + 1, l, mid, mymin(p, n), n);
      getEvaluation(ret_eval[level] + l, g, level + 1, mid, r, mymin(p, n), n);
    }
    
    IL void evaluate(int *a, int *f, int n, int m, int *g) {
      decoNTT(a, 0, 0, m);
      getEvaluation(f, g, 0, 0, m, n, n);
    }
    
    int ans[LOG][MAXN * 8];
    
    void solve1(int *a, int level, int l, int r) {
      if (l + 1 >= r) {
        ans[level][l << 1] = a[l];
        ans[level][l << 1 | 1] = 1;
        return;
      }
      int mid = (l + r) >> 1;
      solve1(a, level + 1, l, mid);
      solve1(a, level + 1, mid, r);
      static int temp[1 << LOG];
      multiply(ans[level + 1] + (l << 1), mid - l + 1, ans[level + 1] + (mid << 1), r - mid + 1, temp);
      std::copy(temp, temp + r - l + 1, ans[level] + (l << 1));
    }
    
    int ret[MAXN * 4];
    
    void solve2(int level, int l, int r) {
      if (l + 1 >= r) {
        ret[l] = 1;
        return;
      }
      int mid = (l + r) >> 1;
      solve2(level + 1, l, mid);
      solve2(level + 1, mid, r);
      static int temp1[1 << LOG], temp2[1 << LOG];
      multiply(ret + l, mid - l, ans[level + 1] + (mid << 1), r - mid + 1, temp1);
      multiply(ans[level + 1] + (l << 1), mid - l + 1, ret + mid, r - mid, temp2);
      inc(temp1, temp2, r - l, ret + l);
    }
    }
    
    int a[MAXN * 4], x[MAXN * 4], y[MAXN * 4], z[MAXN * 4], f[MAXN * 4], g[MAXN * 4], to[MAXN], ans[MAXN];
    
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("p.in", "r", stdin);
      freopen("p.out", "w", stdout);
    #endif
      int n, m;
      scanf("%d%d", &n, &m);
      Poly::init(n * 3 + 5);
      int sum = 0;
      FOR(i, 0, n) {
        scanf("%d", &a[i]);
        sum = add(sum, a[i]);
      }
      Poly::solve1(a, 0, 0, n);
      Poly::solve2(0, 0, n);
      int a = 1, b = 0, c = 0, d = 1, cnt = 0;
      FOR(i, 0, m) {
        int opt;
        scanf("%d", &opt);
        if (opt == 1) {
          int x;
          scanf("%d", &x);
          a = add(a, mul(c, x)), b = add(b, mul(d, x));
        } else {
          std::swap(a, c), std::swap(b, d);
        }
        if (!c) {
          ans[i] = mul(add(mul(sum, a), mul(b, n)), quickPow(d, MOD - 2));
          continue;
        }
        int inv = quickPow(c, MOD - 2);
        x[cnt] = mul(a, inv), y[cnt] = mul(sub(b, mul(d, x[cnt])), inv), z[cnt] = mul(d, inv);
        to[cnt ++] = i;
      }
      Poly::evaluate(z, Poly::ans[0], n + 1, cnt, f);
      Poly::evaluate(z, Poly::ret, n, cnt, g);
      FOR(i, 0, cnt) {
        ans[to[i]] = add(mul(x[i], n), mul(y[i], g[i], quickPow(f[i], MOD - 2)));
      }
      FOR(i, 0, m) {
        printf("%d
    ", ans[i]);
      }
      return 0;
    }
    
  • 相关阅读:
    C# 实现将 PDF 转文本的功能
    推荐大家使用的CSS书写规范、顺序
    Android 应用开发者必看的 9 个 Tips
    网站统计中的数据收集原理及实现
    JSON劫持漏洞攻防原理及演练
    巧妙使用 CSS3 的褪色和动画效果制作消息提醒框
    20条常见的编码陷阱
    11 个最佳 jQuery 滚动条插件
    JavaScript客户端MVC 框架综述
    20个初学者实用的CSS技巧
  • 原文地址:https://www.cnblogs.com/sjkmost/p/12256718.html
Copyright © 2020-2023  润新知