제출 #585772

#제출 시각아이디문제언어결과실행 시간메모리
585772Drew_Copy and Paste 3 (JOI22_copypaste3)C++17
100 / 100
778 ms72884 KiB
#include <bits/stdc++.h> using namespace std; #define pb push_back #define ll long long #define ii pair<int, int> #define f1 first #define s2 second const int prime = 177013; const int mod1 = 1e9 + 9; const int mod2 = 420691273; const int MAX = 2569; const ll inf = 1e18 + 69; template<int KEY1 = mod1, int KEY2 = mod2> struct Hash { template<int MOD> struct Mint { int val; Mint() : val(0) {} Mint(int64_t _val) : val((int)(_val % MOD)) { if (val < 0) val += MOD; } Mint& operator+= (const Mint &rhs) { val += rhs.val; if (val >= MOD) val -= MOD; return *this; } Mint& operator-= (const Mint &rhs) { val -= rhs.val; if (val < 0) val += MOD; return *this; } Mint& operator*= (const Mint &rhs) { val = (int)(1ll * val * rhs.val % MOD); return *this; } friend Mint fpow(Mint x, int64_t y) { Mint res = 1; for (; y > 0; y >>= 1, x *= x) { if (y & 1) res *= x; } return res; } friend Mint inverse(Mint x) { return fpow(x, MOD-2); } Mint& operator/= (const Mint &rhs) { return *this *= inverse(rhs); } friend Mint operator+ (Mint a, const Mint &b) { return a += b; } friend Mint operator- (Mint a, const Mint &b) { return a -= b; } friend Mint operator- (Mint a) { return 0 - a; } friend Mint operator* (Mint a, const Mint &b) { return a *= b; } friend Mint operator/ (Mint a, const Mint &b) { return a /= b; } friend ostream& operator<< (ostream &os, const Mint &a) { return os << a.val; } friend bool operator== (const Mint &a, const Mint &b) { return a.val == b.val; } friend bool operator!= (const Mint &a, const Mint &b) { return a.val != b.val; } }; Mint<KEY1> val1; Mint<KEY2> val2; Hash() : val1(0), val2(0) {} Hash(int64_t _val) : val1(_val), val2(_val) {} Hash& operator+= (const Hash &rhs) { val1 += rhs.val1; val2 += rhs.val2; return *this; } Hash& operator-= (const Hash &rhs) { val1 -= rhs.val1; val2 -= rhs.val2; return *this; } Hash& operator*= (const Hash &rhs) { val1 *= rhs.val1; val2 *= rhs.val2; return *this; } Hash& operator/= (const Hash &rhs) { val1 /= rhs.val1; val2 /= rhs.val2; return *this; } friend Hash operator+ (Hash a, const Hash &b) { return a += b; } friend Hash operator- (Hash a, const Hash &b) { return a -= b; } friend Hash operator- (Hash a) { return 0 - a; } friend Hash operator* (Hash a, const Hash &b) { return a *= b; } friend Hash operator/ (Hash a, const Hash &b) { return a /= b; } friend ostream& operator<< (ostream &os, const Hash &a) { return os << a.val1 << " " << a.val2; } friend bool operator== (const Hash &a, const Hash &b) { return a.val1 == b.val1 && a.val2 == b.val2; } friend bool operator!= (const Hash &a, const Hash &b) { return a.val1 != b.val1 || a.val2 != b.val2; } }; ll A, B, C; int N; char s[MAX]; Hash<> pwr[MAX], inv[MAX], pfx[MAX]; int nxt[MAX][MAX]; // nxt[l][r]: smallest `x` such that x >= r and s.substr(l, r-l) = s.substr(x, r-l) ll dp[MAX][MAX]; // dp[l][r]: lowest cost to make x == "" and y == s.substr(l, r-l) int main() { ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0); pwr[0] = 1; for (int i = 1; i < MAX; ++i) pwr[i] = prime * pwr[i-1]; inv[MAX-1] = 1 / (pwr[MAX-1]); for (int i = MAX-2; i >= 0; --i) inv[i] = prime * inv[i+1]; for (auto &x : dp) for (auto &y : x) y = inf; cin >> N >> s >> A >> B >> C; pfx[0] = s[0]; for (int i = 1; i < N; ++i) pfx[i] = pfx[i-1] + s[i] * pwr[i]; const auto getSum = [&](int l, int r) -> ii { Hash<> tmp = (pfx[r] - (l ? pfx[l-1] : 0)) * inv[l]; return { tmp.val1.val, tmp.val2.val }; }; for (int len = 1; len <= N; ++len) { map<ii, vector<int>> memo; for (int l = 0; l+len <= N; ++l) memo[getSum(l, l+len-1)].pb(l); for (const auto &[x, v] : memo) { // cerr << "HAHA\n"; for (int i = 0, j = 0, sz = (int)v.size(); i < sz; ++i) { while (j < sz && v[i]+len > v[j]) ++j; nxt[v[i]][v[i] + len] = (j == sz ? N : v[j]); } } } for (int i = 0; i < N; ++i) dp[i][i+1] = A + B; for (int len = 1; len < N; ++len) { for (int l = 0; l+len <= N; ++l) { int r = l + len; if (l) dp[l-1][r] = min(dp[l-1][r], dp[l][r] + A); if (r+1 <= N) dp[l][r+1] = min(dp[l][r+1], dp[l][r] + A); for(int cur = l, ctr = 1; nxt[cur][cur + len] < N;) { cur = nxt[cur][cur + len]; ctr++; dp[l][cur + len] = min(dp[l][cur + len], dp[l][r] + C*ctr + A*(cur+len - l - ctr*len) + B); } } } cout << dp[0][N] - B << '\n'; return 0; }
#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...