AtCoder

ABC350 E問題(Toward 0)を解く

AtCoder_ABC350_E

AtCoder が提供しているABC(AtCoder Beginner Contest)350 のE問題をC++とPythonで解いてみました。ABC350は、2024年4月20日21:00に実施されました。

AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。

E問題 Toward 0(Difficulty : 1385)

問題はリンク先をご覧ください。

ABC350 E問題 Toward 0

期待値のDPとして解くことができます。メモ化再帰を使います。AtCoder Problems による Difficulty は 1385 でした。

解答案

問題の見た目が異なりますが、ABC300 E問題解説記事)は同じような考え方で解くことができました。

dp[i] を整数 i に対して、操作を繰り返して 0 になるまでに支払う金額の期待値とします。2種類の操作のうち2番目の操作だけを考えます。

dp[i] = Y + 1/6(dp[i] + dp[i/2] + dp[i/3] + dp[i/4] + dp[i/5] + dp[i/6])

式を整理すると、以下となります。

dp[i] = 6 / 5 Y + 1/5(dp[i] + dp[i/2] + dp[i/3] + dp[i/4] + dp[i/5] + dp[i/6])

また、dp[0] = 0 です。この式に1番目の操作も加えます。ふたつの操作の結果で小さい値が dp[i] となります。dp[N] が解となります。

C++ プログラム例(ABC350E)

今回はDPを再帰を使って実装します。素の実装では間に合わないため、メモ化再帰を使います。

再帰関数の補足です。

  • 引数が0なら0を返す。
  • メモとして記憶されているならメモの値を返す。
  • そうでないなら、漸化式に従って再帰的に値を計算する(19ー23行目)。

以下が、C++プログラムとなります。

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long int ull;

ull n, a, x, y;
map<ull, double> memo;

double rec(ull n)
{
	if (n == 0) {
		return 0.0;
	}

	if (memo.find(n) != memo.end()) {
		return memo[n];
	}

	double t = 6.0 / 5.0 * (double)y;
	for (int i = 2; i <= 6; ++i) {
		t += rec(n / i) / 5.0;
	}
	double result = min((double)x + rec(n / a), t);
	memo[n] = result;

	return result;
}

int main()
{
	cin >> n >> a >> x >> y;

	cout << fixed << setprecision(15);
	cout << rec(n) << endl;

	return 0;
}

AC(Accepted=正しいプログラム)と判定されました。

Python プログラム例(ABC350E)

Python 3.9 以降では、cache というデコレータが使えます(2、5行目)。メモ化再帰の処理が隠されたため、すっきりと書けています。以下となります。

"""AtCoder Beginner Contest 350 E"""
import functools


@functools.cache
def rec(n):
    global a, x, y

    if n == 0:
        return 0.0

    t = 6.0 / 5.0 * y
    for i in range(2, 7):
        t += rec(n // i) / 5.0

    result = min(x + rec(n // a), t)

    return result


n, a, x, y = map(int, input().split())
print(rec(n))

こちらも「AC」と判定されました。

最後に

Pythonのデコレータを紹介するのは3回目です。ABC275D問題ABC340C問題でした。メモ化再帰もそれだけ使っていることになります。繰り返して使っていれば習得できると考えています。

引き続き ABC の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA