답안 #564973

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
564973 2022-05-20T06:09:54 Z Zanite Copy and Paste 3 (JOI22_copypaste3) C++17
0 / 100
44 ms 98508 KB
#include <bits/stdc++.h>
using namespace std;

using ll	= long long;
using pll	= pair<ll, ll>;

#define fi	first
#define se	second

const ll mod	= 1707726299;
const ll maxN	= 2505;
const ll maxNr	= 2500;
const ll INF	= 1e18;

void maddto(ll &x, ll y) {x += y; x %= mod;}
ll msub(ll x, ll y) {x -= y; while (x < 0) x += mod; x %= mod; return x;}
ll mmul(ll x, ll y) {x *= y; x %= mod; return x;}

void chmin(ll &x, ll y) {x = min(x, y);}

ll modexp(ll x, ll y) {
	if (!x) return 0; if (!y) return 1;
	ll t = modexp(x, y >> 1);
	return mmul(t, mmul(t, (y & 1) ? x : 1));
}

ll A, B, C, N;
char S[maxN];

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<ll> uid(1e5, 2e5);
ll key = uid(rng), invkey = modexp(key, mod-2);
ll kpow[maxN], invkpow[maxN], hsh[maxN];

ll dp[maxN][maxN], nxt[maxN][maxN];

void precomp() {
	key = rng();
	invkey = modexp(key, mod-2);
	kpow[0] = invkpow[0] = 1;
	for (ll i = 1; i <= maxNr; i++) {
		kpow[i] = mmul(kpow[i-1], key);
		invkpow[i] = mmul(invkpow[i-1], invkey);
	}
}

void hashS() {
	for (ll i = 1; i <= N; i++) {
		hsh[i] = mmul(S[i], kpow[i]);
		maddto(hsh[i], hsh[i-1]);
	}
}

ll getHash(ll l, ll r) {
	ll ret = msub(hsh[r], hsh[l-1]);
	return mmul(ret, invkpow[l-1]);
}

int main() {
	precomp();

	scanf("%lld %lld %lld", &A, &B, &C);
	S[0] = '#';
	scanf("%s", S + 1);
	N = strlen(S) - 1;

	hashS();

	// compute nxt[l][r] for each possible substring length
	memset(nxt, -1, sizeof(nxt));
	for (ll len = 1; len < N; len++) {
		vector<pll> hashes = {{-1, -1}};
		for (ll st = 1; st <= N-len+1; st++) {
			hashes.push_back({getHash(st, st+len-1), st});
		}
		sort(hashes.begin(), hashes.end());
		/*
		for (auto H : hashes) {
			printf("{%lld, %lld} ", H.fi, H.se);
		}
		cout << '\n';
		*/

		deque<ll> pending;
		for (ll i = 1; i < hashes.size(); i++) {
			if (hashes[i].fi != hashes[i-1].fi) {
				pending.clear();
			}
			while (!pending.empty()) {
				if (pending.front() <= hashes[i].se - len) {
					nxt[pending.front()][pending.front()+len-1] = hashes[i].se;
					pending.pop_front();
				} else break;
			}
			pending.push_back(hashes[i].se);
		}
	}

	/*
	for (ll l = 1; l <= N; l++) {
		for (ll r = l; r <= N; r++) {
			printf("nxt[%lld][%lld] = %lld\n", l, r, nxt[l][r]);
		}
	}
	*/

	// Calculate DP
	for (auto &i : dp) {
		for (auto &j : i) {
			j = INF;
		}
	}
	// Base case
	for (ll i = 1; i < N; i++) {
		dp[i][i] = A + B;
	}
	// Transition
	for (ll len = 1; len < N; len++) {
		for (ll l = 1; l <= N-len+1; l++) {
			ll r = l+len-1;

			// Type S[l-1]
			if (l > 1) {
				chmin(dp[l-1][r], dp[l][r] + A);
			}

			// Type S[r+1]
			if (r < N) {
				chmin(dp[l][r+1], dp[l][r] + A);
			}

			// Paste next occurences of S[l..r]
			ll cur = l, pastes = 1;
			while (nxt[cur][cur+len-1] != -1) {
				cur = nxt[cur][cur+len-1];
				pastes++;
				chmin(
					dp[l][cur+len-1],
					dp[l][r] + 1ll * pastes * C + 1ll * (cur+len-l - 1ll * len * pastes) * A + B
				);
			}
		}
	}

	printf("%lld\n", dp[1][N] - B);
}

Compilation message

copypaste3.cpp: In function 'll modexp(ll, ll)':
copypaste3.cpp:22:2: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
   22 |  if (!x) return 0; if (!y) return 1;
      |  ^~
copypaste3.cpp:22:20: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   22 |  if (!x) return 0; if (!y) return 1;
      |                    ^~
copypaste3.cpp: In function 'int main()':
copypaste3.cpp:85:20: warning: comparison of integer expressions of different signedness: 'll' {aka 'long long int'} and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   85 |   for (ll i = 1; i < hashes.size(); i++) {
      |                  ~~^~~~~~~~~~~~~~~
copypaste3.cpp:62:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   62 |  scanf("%lld %lld %lld", &A, &B, &C);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
copypaste3.cpp:64:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   64 |  scanf("%s", S + 1);
      |  ~~~~~^~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 44 ms 98508 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 40 ms 98508 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 44 ms 98508 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 44 ms 98508 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 44 ms 98508 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 44 ms 98508 KB Output isn't correct
2 Halted 0 ms 0 KB -