【封装工程】OI/ACM常用封装

前言

笔者有的时候无聊,就将一些奇怪的东西封装起来。

范围主要是在\(OI\)或者\(ACM\)中的常见数据结构等。

随着笔者的能力的提升,可能会对原来的封装程序进行修改,并且保留原来的版本。

【ST表(静态RMQ)】

// program at 2019-11-12
template <class T, int N, int M>
struct ST {
  T f[N + 5][M + 1];
  int log2[N];
  T compare(T x, T y) { // can change, depend on the priority of problem
    return x < y ? x : y;
  }
  void init(int* a) {
    log2[0] = -1;
    for (int i = 1; i <= N; i++)
      f[i][0] = a[i], log2[i] = log2[i >> 1] + 1;
    for (int j = 1; j <= M; j++)
      for (int i = 1; i + (1 << j) - 1 <= N; i++)
        f[i][j] = compare(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
  }
  T query(int l, int r) {
    int k = log2[r - l + 1];
    return compare(f[l][k], f[r - (1 << k) + 1][k]);
  }
};

高精度

四位压位高精,支持高精加高精、高精减高精(\(a>b\))、高精乘高精、高精乘低精。

// program at 2019-11-14
struct bigint {
  static const int BASE = 10000;
  static const int SIZE = 105
  int len, a[SIZE];
  bigint() {
    memset(a, 0, sizeof a);
    len = 1;
  }
  bigint(long long x) { *this = x; }
  void operator=(int x) {
    len = 0;
    while (x) {
      a[++len] = x % BASE;
      x /= BASE;
    }
  }

  friend bigint operator+(bigint a, bigint b) {
    bigint c;
    c.len = max(a.len, b.len) + 1;
    for (int i = 1, x = 0; i <= c.len; i++)
      c.a[i] = a.a[i] + b.a[i] + x, x = c.a[i] / BASE, c.a[i] %= BASE;
    while (!c.a[c.len]) c.len--;
    return c;
  }

  friend bigint operator-(bigint a, bigint b) {
    a.len = max(a.len, b.len);
    for (int i = 1; i <= a.len; i++) {
      if (a.a[i] < b.a[i])
        a.a[i] += BASE, a.a[i + 1]--;
      a.a[i] -= b.a[i];
    }
    while (!a.a[a.len]) a.len--;
    return a;
  }

  friend bigint operator*(bigint a, bigint b) {
    bigint c;
    c.len = a.len + b.len;
    for (int i = 1; i <= a.len; i++) {
      int x = 0;
      for (int j = 1; j <= b.len; j++)
        c.a[i + j - 1] += a.a[i] * b.a[j] + x, x = c.a[i + j - 1] / BASE, c.a[i + j - 1] %= BASE;
      c.a[b.len + i] = x;
    }
    while (!c.a[c.len]) c.len--;
    return c;
  }

  friend bigint operator*(bigint a, int b) {
    a.len += 3;
    for (int i = 1; i <= a.len; i++) a.a[i] *= b;
    for (int i = 1; i <= a.len; i++) a.a[i + 1] += a.a[i] / BASE, a.a[i] %= BASE;
    while (!a.a[a.len]) a.len--;
    return a;
  }

  void print() {
    printf("%d", a[len]);
    for (int i = len - 1; i >= 1; i--) printf("%04d", a[i]);
    puts("");
  }

  bigint& operator+=(bigint b) {
    *this = *this + b;
    return *this;
  }

  bigint& operator-=(bigint b) {
    *this = *this - b;
    return *this;
  }

  bigint& operator*=(bigint b) {
    *this = *this * b;
    return *this;
  }
};
上一篇:OI/ACM最全卡常大招


下一篇:工具系列 | PHPSTROM 连接Docker容器 && 配置XDEBUG调试