Submission #673636

#TimeUsernameProblemLanguageResultExecution timeMemory
673636peijarCopy and Paste 3 (JOI22_copypaste3)C++17
100 / 100
932 ms49712 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;

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; }
};

const int MOD1 = 1e9 + 9, MOD2 = 1e9 + 7;

template <typename T1, typename T2> struct ModPair {
  T1 x;
  T2 y;

  ModPair() : x(0), y(0) {}

  ModPair(int u) : x(u), y(u) {}

  ModPair(T1 _x, T2 _y) : x(_x), y(_y) {}

  ModPair &operator+=(const ModPair &other) {
    x += other.x;
    y += other.y;
    return *this;
  }

  ModPair &operator*=(const ModPair &other) {
    x *= other.x;
    y *= other.y;
    return *this;
  }

  ModPair &operator-=(const ModPair &other) {
    x -= other.x;
    y -= other.y;
    return *this;
  }

  friend ModPair operator+(const ModPair &a, const ModPair &b) {
    return ModPair(a) += ModPair(b);
  }
  friend ModPair operator-(const ModPair &a, const ModPair &b) {
    return ModPair(a) -= ModPair(b);
  }
  friend ModPair operator*(const ModPair &a, const ModPair &b) {
    return ModPair(a) *= ModPair(b);
  }

  bool operator<(const ModPair &o) const { return pair(x, y) < pair(o.x, o.y); }
  bool operator>(const ModPair &o) const { return pair(x, y) > pair(o.x, o.y); }
  bool operator<=(const ModPair &o) const {
    return pair(x, y) <= pair(o.x, o.y);
  }
  bool operator>=(const ModPair &o) const {
    return pair(x, y) >= pair(o.x, o.y);
  }
  bool operator==(const ModPair &o) const {
    return pair(x, y) == pair(o.x, o.y);
  }

  ModPair inv() { return ModPair(x.inv(), y.inv()); };
};

using Mint = ModPair<ModInt<MOD1>, ModInt<MOD2>>;

const int MAXN = 2501;
const int INF = 1e18;

Mint powBase[MAXN], invPow[MAXN];
int N, costAdd, costCut, costPaste;
string s;
vector<Mint> prefPow;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int randint(int lb, int ub) {
  return uniform_int_distribution<int>(lb, ub)(rng);
}

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

  int BASE = randint(300, 400);

  powBase[0] = 1;
  for (int i = 1; i < MAXN; ++i)
    powBase[i] = powBase[i - 1] * BASE;
  invPow[MAXN - 1] = powBase[MAXN - 1].inv();
  for (int i = MAXN - 1; i > 0; --i)
    invPow[i - 1] = invPow[i] * BASE;

  cin >> N >> s >> costAdd >> costCut >> costPaste;
  prefPow.resize(N + 1);

  for (int i = 0; i < N; ++i)
    prefPow[i + 1] = prefPow[i] + powBase[i] * s[i];

  vector<vector<int>> dp(N + 1, vector<int>(N + 1, INF));

  for (int len = 0; len <= N; ++len) {
    map<Mint, vector<int>> occs;
    for (int deb = 0; deb + len <= N; ++deb) {
      dp[deb][deb + len] = min(dp[deb][deb + len], len * costAdd);
      if (len)
        dp[deb][deb + len] =
            min(dp[deb][deb + len],
                min(dp[deb + 1][deb + len], dp[deb][deb + len - 1]) + costAdd);
      Mint x = (prefPow[deb + len] - prefPow[deb]) * invPow[deb];
      occs[x].push_back(deb);
    }
    if (!len)
      continue;

    for (auto &[x, vec] : occs) {
      for (int i = 0; i < (int)vec.size(); ++i) {
        int nbOccs = 0;
        int curPos = vec[i];
        while (true) {
          nbOccs++;
          dp[vec[i]][curPos + len] =
              min(dp[vec[i]][curPos + len],
                  dp[vec[i]][vec[i] + len] +
                      costAdd * (curPos + len - vec[i] - nbOccs * len) +
                      costCut + costPaste * nbOccs);
          int j =
              lower_bound(vec.begin(), vec.end(), curPos + len) - vec.begin();
          if (j == (int)vec.size())
            break;
          curPos = vec[j];
        }
      }
    }
  }
  cout << dp[0][N] << endl;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...