数据过水
查看原帖
数据过水
428908
wzj33300逆室奈隆楼主2024/5/31 23:37

这是我的板子

#ifndef MATH_BIGNUM_H_
#define MATH_BIGNUM_H_ 1
#include <string.h>

#include <algorithm>
#include <string>
#include <vector>

template <typename T>
auto HasOperatorRightString(int) -> decltype(std::declval<T>() >>
                                                 std::declval<std::string&>(),
                                             std::true_type{});

template <typename T>
std::false_type HasOperatorRightString(...);

template <typename T>
using HasOperatorRightStringT = decltype(HasOperatorRightString<T>(0));

template <typename T>
auto HasOperatorLeftChar(int) -> decltype(std::declval<T>()
                                              << std::declval<char>(),
                                          std::true_type{});

template <typename T>
std::false_type HasOperatorLeftChar(...);

template <typename T>
using HasOperatorLeftCharT = decltype(HasOperatorLeftChar<T>(0));

template <typename T>
auto HasOperatorLeftInt(int) -> decltype(std::declval<T>()
                                             << std::declval<int>(),
                                         std::true_type{});

template <typename T>
std::false_type HasOperatorLeftChar(...);

template <typename T>
using HasOperatorLeftIntT = decltype(HasOperatorLeftInt<T>(0));

struct bign {
  using ll = long long;
  static const int BIT = 8, MOD = 1e8, maxlen = 1e4 + 5;
  std::vector<int> a;
  bool f;
  bign() { a.clear(), f = false; }
  bign(const char* s) {
    int i = 0, l = strlen(s), j;
    if (a.clear(), f = false, s[0] == '-') i = f = true;
    if (s[i] == '0') return;
    j = (l - i - 1) % BIT + 1, a.push_back(0);
    for (; i < l; (a.back() *= 10) += s[i++] - 48, --j)
      if (!j) a.push_back(0), j = BIT;
    std::reverse(a.begin(), a.end());
  }
  bign(const std::string& s) { *this = s.c_str(); }
  bign(int x) {
    a.clear(), x < 0 ? (x = -x, f = true) : (f = false);
    if (x)
      x < MOD ? (a.push_back(x)) : (a.push_back(x % MOD), a.push_back(x / MOD));
  }
  bign(ll x) {
    a.clear(), x < 0 ? (x = -x, f = true) : (f = false);
    while (x > MOD) a.push_back(x % MOD), x /= MOD;
    a.push_back(x);
  }
  template <typename T>
  friend typename std::enable_if<HasOperatorRightStringT<T>::value, T&>::type
  operator>>(T& in, bign& x) {
    std::string c;
    in >> c;
    x = c;
    return in;
  }
  template <typename T>
  friend typename std::enable_if<
      HasOperatorLeftIntT<T>::value && HasOperatorLeftCharT<T>::value, T&>::type
  operator<<(T& out, const bign& x) {
    int i = x.a.size();
    if (!i) return out << '0';
    if (x.f) out << '-';
    char sw[BIT + 1];
    for (out << x.a[--i]; i--;) {
      for (int j = 0; j < BIT; j++) {
        sw[j] = '0';
      }
      sw[BIT] = '\0';
      int l = BIT;
      int al = x.a[i];
      while (al) {
        sw[--l] = al % 10 + '0';
        al /= 10;
      }
      out << sw;
    }
    return out;
  }
  explicit operator int() {
    int l = a.size(), i, r = 0;
    for (i = l - 1; ~i; --i) r = r * MOD + a[i];
    return f ? -r : r;
  }
  explicit operator ll() {
    int l = a.size(), i;
    ll r = 0;
    for (i = l - 1; ~i; --i) r = r * MOD + a[i];
    return f ? -r : r;
  }
  explicit operator bool() const { return !a.empty(); }
  int abscmp(const bign& x) const {
    int l = a.size(), o = x.a.size();
    if (l != o) return l < o ? -1 : 1;
    while (l--)
      if (a[l] != x.a[l]) return a[l] < x.a[l] ? -1 : 1;
    return 0;
  }
  int cmp(const bign& x) const {
    if (a.empty()) return x.a.empty() ? 0 : (x.f ? 1 : -1);
    if (x.a.empty()) return f ? -1 : 1;
    if (!f && x.f) return 1;
    if (f && !x.f) return -1;
    return f ? -abscmp(x) : abscmp(x);
  }
  friend bool operator<(const bign& x, const bign& y) { return x.cmp(y) < 0; }
  friend bool operator>(const bign& x, const bign& y) { return x.cmp(y) > 0; }
  friend bool operator<=(const bign& x, const bign& y) { return x.cmp(y) <= 0; }
  friend bool operator>=(const bign& x, const bign& y) { return x.cmp(y) >= 0; }
  friend bool operator==(const bign& x, const bign& y) { return x.cmp(y) == 0; }
  friend bool operator!=(const bign& x, const bign& y) { return x.cmp(y) != 0; }
  bign& operator+() { return *this; }
  bign operator-() {
    bign x = *this;
    return x.f ^= 1, x;
  }
  void add1() {
    if (++a[0] == MOD) {
      a.push_back(0);
      for (int i = 0; a[i] == MOD; ++i) a[i] = 0, ++a[i + 1];
      if (!a.back()) a.pop_back();
    }
  }
  void sub1() {
    if (--a[0] == -1) {
      for (int i = 0; a[i] == -1; ++i) a[i] += MOD, --a[i + 1];
      if (!a.back()) a.pop_back();
    }
  }
  bign& operator++() {
    return a.empty() ? (a.push_back(1), f = false, void())
                     : (f ? sub1() : add1()),
           *this;
  }
  bign& operator--() {
    return a.empty() ? (a.push_back(1), f = true, void())
                     : (f ? add1() : sub1()),
           *this;
  }
  bign operator++(int) {
    bign x = *this;
    return a.empty() ? (a.push_back(1), f = false, void())
                     : (f ? sub1() : add1()),
           x;
  }
  bign operator--(int) {
    bign x = *this;
    return a.empty() ? (a.push_back(1), f = true, void())
                     : (f ? add1() : sub1()),
           x;
  }
  void fit() {
    while (!a.empty() && !a.back()) a.pop_back();
  }
  void add(const bign& x) {
    int i, l = a.size(), o = x.a.size(), j;
    if (l < o) a.resize(o);
    a.push_back(0);
    for (i = 0; i < o; ++i) {
      j = a[i] + x.a[i];
      if (j >= MOD) j -= MOD, ++a[i + 1];
      a[i] = j;
    }
    fit();
  }
  void sub(const bign& x) {
    int i, l = a.size(), o = x.a.size(), j;
    for (i = 0; i < o; ++i) {
      j = a[i] - x.a[i];
      if (j < 0) j += MOD, --a[i + 1];
      a[i] = j;
    }
    for (i = o; i < l; ++i)
      if (a[i] < 0) a[i] += MOD, --a[i + 1];
    fit();
  }
  void mul(const bign& x) {
    int i, j, l = a.size(), o = x.a.size(), k = l + o;
    std::vector<long long> C(k + 2, 0);
    for (i = 0; i < o; ++i)
      for (j = 0; j < l; ++j) C[i + j] += x.a[i] * 1ll * a[j];
    for (i = 0, a.resize(k); i < k; ++i)
      C[i + 1] += C[i] / MOD, a[i] = C[i] % MOD;
    fit();
  }
  int div(const int& x) {
    int i, l = a.size();
    ll w = 0;
    for (i = l - 1; ~i; --i)
      w = w * MOD + a[i], a[i] = w / x, w -= ll(a[i]) * x;
    return fit(), w;
  }
  bign div(const bign& x) {
    int i, l = a.size(), o = x.a.size(), j = l - o;
    ll u, v, w;
    bign r, k = x;
    k.f = false;
    if (j < 0) return r = *this, *this = 0, r;
    for (i = l - 1; i > j; --i) r = r * MOD + a[i];
    for (i = j, a.resize(j + 1); ~i; --i) {
      r = r * MOD + a[i], u = 0, v = MOD;
      while (v - u > 1) {
        w = (u + v) >> 1;
        if (k * w <= r)
          u = w;
        else
          v = w;
      }
      a[i] = u, r -= k * a[i];
    }
    return fit(), r;
  }
  bign divnew(const bign& x) {
    int i, l = a.size(), o = x.a.size(), j = l - o;
    ll u, v, w;
    bign r, k = x;
    k.f = false;
    if (j < 0) return r = *this, *this = 0, r;
    for (i = l - 1; i > j; --i) r = r * MOD + a[i];
    for (i = j, a.resize(j + 1); ~i; --i) {
      r = r * MOD + a[i], u = 0, v = MOD;
      while (v - u > 1) {
        w = (u + v) >> 1;
        if (k * w <= r)
          u = w;
        else
          v = w;
      }
      a[i] = u, r -= k * a[i];
    }
    if (f) r = -r;
    f = (f != x.f);
    return fit(), r;
  }
  bign& operator+=(const bign& x) {
    if (f == x.f)
      add(x);
    else if (abscmp(x) >= 0)
      sub(x);
    else {
      bign y = x;
      y.sub(*this), *this = y;
    }
    return *this;
  }
  bign& operator-=(const bign& x) {
    if (f != x.f)
      add(x);
    else if (abscmp(x) >= 0)
      sub(x);
    else {
      bign y = x;
      y.sub(*this), *this = y, f = !f;
    }
    return *this;
  }
  bign& operator*=(const bign& x) { return mul(x), f = (f != x.f), *this; }
  bign& operator/=(const int& x) {
    return div(abs(x)), f = !((f && x < 0) || (!f && x > 0)), *this;
  }
  bign& operator/=(const bign& x) { return div(x), f = (f != x.f), *this; }
  bign& operator/=(const ll& x) { return *this /= (bign)x; }
  bign& operator%=(const int& x) {
    return *this = f ? -div(abs(x)) : div(abs(x));
  }
  bign& operator%=(const bign& x) { return *this = (f ? -div(x) : div(x)); }
  bign& operator%=(const ll& x) { return *this %= (bign)x; }
  friend bign operator+(bign x, const bign& y) { return x += y, x; }
  friend bign operator-(bign x, const bign& y) { return x -= y, x; }
  friend bign operator*(bign x, const bign& y) { return x *= y, x; }
  friend bign operator/(bign x, const ll& y) { return x /= y, x; }
  friend bign operator/(bign x, const int& y) { return x /= y, x; }
  friend bign operator/(bign x, const bign& y) { return x /= y, x; }
  friend bign operator%(bign x, const ll& y) { return x %= y, x; }
  friend bign operator%(bign x, const int& y) { return x %= y, x; }
  friend bign operator%(bign x, const bign& y) { return x %= y, x; }
};
void swap(bign& x, bign& y) { std::swap(x.f, y.f), std::swap(x.a, y.a); }
bign abs(bign x) { return x.f = false, x; }
bign pow(bign a, int b) {
  bign r = 1;
  for (; b; b >>= 1) {
    if (b & 1) r *= a;
    a *= a;
  }
  return r;
}
bign gcd(bign a, bign b) {
  bign r = 1;
  while (true) {
    if (!a || !b) return (a + b) * r;
    while (a.a[0] >> 1 == 0 && b.a[0] >> 1 == 0) r *= 2, a /= 2, b /= 2;
    while (a.a[0] >> 1 == 0) a /= 2;
    while (b.a[0] >> 1 == 0) b /= 2;
    if (a < b) swap(a, b);
    a -= b;
  }
}

#endif

在本题上可以 AC,但这个乘法很明显是有问题的,压 8 位,所以乘起来后单个位置的值可以为

(108−1)×(108−1)×⌊1048⌋\left(10^8-1\right)\times \left(10^8-1\right)\times \left \lfloor \frac{10^4}{8} \right \rfloor

很明显这个值大于 long long 可存储的最大值。

可以通过以下程序 hack 它。

#include "bignum.h"

#include <bits/stdc++.h>

int main() {
  std::string a = "";
  for (int i = 0; i < 1e4; i++) {
    a += '9';
  }
  bign x(a), y(a);
  std::cout << x * y << std::endl;
  return 0;
}
2024/5/31 23:37
加载中...