Bondo416さんの鹿島建設プログラミングコンテスト2024(AtCoder Beginner Contest 340)での成績:726位
— ボンド@競プロ (@bond_cmprog) February 10, 2024
パフォーマンス:1672相当
レーティング:1576→1586 (+10) :)#AtCoder #鹿島建設プログラミングコンテスト2024(ABC340) https://t.co/E2P5A9qxry
A - Arithmetic Progression
for文で出力する
void solve() { int A, B, D; cin >> A >> B >> D; for (int i = A; i <= B; i += D) { cout << i << " "; } cout << endl; }
B - Append
vectorなどで実際に値を追加していき、各クエリに答えれば良い
void solve() { int Q; cin >> Q; vector<int> A; while (Q--) { int q, x; cin >> q >> x; if (q == 1) A.emplace_back(x); else { int n = A.size(); cout << A[n - x] << endl; } } }
C - Divide and Divide
再帰関数などで操作をシミュレートできる
同じ値に対して愚直にシミュレートするとTLEするのでメモ化再帰することで間に合うようになる
void solve() { ll N; cin >> N; map<ll, ll> dp; dp[0] = 0; auto dfs = [&](auto &&self, ll n) -> ll { if (dp.contains(n)) return dp[n]; if (n == 1) return 0; ll res = n; res += self(self, ceil_div(n, 2)) + self(self, floor_div(n, 2)); dp[n] = res; return dp[n]; }; cout << dfs(dfs, N) << endl; }
D - Super Takahashi Bros.
与えられた入力をグラフと見なすことでダイクストラで解くことができる
void solve() { int N; cin >> N; vector<ll> A(N), B(N), X(N); REP(i, N - 1) { cin >> A[i] >> B[i] >> X[i]; --X[i]; } vector<ll> dist(N, LINF); dist[0] = 0; priority_queue<LP, vector<LP>, greater<LP>> pq; pq.push({0, 0}); while (!pq.empty()) { auto [d, v] = pq.top(); pq.pop(); if (dist[v] < d) continue; dumps(d, v); if (v < N - 1) { int nv = v + 1; ll nd = d + A[v]; if (chmin(dist[nv], nd)) pq.push({nd, nv}); } if (v < N - 1) { int nv = X[v]; ll nd = d + B[v]; if (chmin(dist[nv], nd)) pq.push({nd, nv}); } } cout << dist[N - 1] << endl; }
E - Mancala 2
$ B_i $ の箱に入っているボールの個数を $ X $ とすると、すべての箱に $ \lfloor \frac{X}{N} \rfloor $ 個のボールを入れ、残りの $ X \pmod{N} $ 個のボールを $ B_i + 1 $ から順に入れていく操作になる
これは1点変更・区間加算のクエリの操作ができれば良いので遅延セグメント木などを使えば良い
void solve() { ll N, M; cin >> N >> M; vector<ll> A(N), B(M); REP(i, N) cin >> A[i]; REP(i, M) cin >> B[i]; lazy_segtree<S, op, e, F, mapping, composition, id> seg(A); REP(i, M) { ll id = B[i]; ll x = seg.prod(id, id + 1); seg.set(id, 0); ll all = x / N; seg.apply(0, N, all); ll rest = x % N; seg.apply(id + 1, min(id + 1 + rest, N), 1); rest = rest - (min(id + 1 + rest, N) - (id + 1)); seg.apply(0, max(0LL, rest), 1); } REP(i, N) cout << seg.prod(i, i + 1) << " "; cout << endl; }
F - S = 1
三角形の面積公式から、$ (X, Y) $ の座標を使って $ |AY - BX| = 2 $ と表すことができる
よって、$ ax + by = c $ の不定方程式を解ければ良い
$ AY - BX = 2 $ が解を持つには $ 2 \equiv 0 \pmod{gcd(X, Y)} $ であれば良い
後は、拡張ユークリッドの互除法で実際に解を求めることができる
求めた解は $ c = gcd(X, Y) $ のときの解であるため、$ \frac{2}{gcd(X,Y)} $ 倍して出力する
参考
long long extGCD(long long a, long long b, long long &x, long long &y) { if (b == 0) { x = 1; y = 0; return a; } long long d = extGCD(b, a % b, y, x); y -= a / b * x; return d; } void solve() { ll X, Y; cin >> X >> Y; if (2 % gcd(X, Y) != 0) { cout << -1 << endl; return; } ll x, y; extGCD(-Y, X, x, y); cout << 2 / gcd(X, Y) * x << " " << 2 / gcd(X, Y) * y << endl; }