結構頭がこんがらがる問題だと思う。
問題概要
あるソーシャルゲームでは、1 日につき 1 回までログインすることができ、ログインするたびに 枚のコインが得られる。
さらに、月曜日から日曜日まで 7 日連続でログインすると、そのたびに、追加で 枚のコインが得られる。
明日は月曜日である。 枚のコインを得るために必要な日数の最小値を求めよ。
制約
解法 (1):シミュレーション
まず最もオーソドックスな方法として、日々のログインによって積み上げられるコイン総数をシミュレーションしていく方法が考えられます。
つまり、はじめて 枚以上となった時点でシミュレーションを打ち切る方法が考えられます。while
文などが活用できます。具体的には、次のコードのように実装できます。
コード
#include <iostream> using namespace std; int A, B, C; int main() { cin >> A >> B >> C; int res = 0; int cur = 0; for (int i = 1;; ++i) { cur += A; if (i % 7 == 0) cur += B; if (cur >= C) { res = i; break; } } cout << res << endl; }
解法 (2):計算で求める
シミュレーションすることなく、直接計算で求めることもできます。まず、
1 週間ごとにコインが 枚得られる
ということに着目しましょう。そこで、 を で割った商を 、余りを とすると、次のように整理できます。
- 週間ログインを続けると
- コインの残り必要枚数が 枚となる
最後に、残りの 枚を稼ぐために必要な日数を求めましょう。つまり、1 日 枚ずつ積み上げて 枚以上となる日数を求めましょう。
これは、いわゆる切り上げ処理です。次の記事の方法によって、
(r + A - 1) / r
と求められます。ただし、これが 7 を超える場合は 7 としましょう。
以上の解法をまとめると、次のように実装できます。
コード
#include <bits/stdc++.h> using namespace std; int main() { int A, B, C; cin >> A >> B >> C; int coins_per_week = A * 7 + B; // 1 週間あたりのコイン枚数 int weeks = C / coins_per_week; // 必要週数 int nokori_coins = C % coins_per_week; int nokori_days = min((nokori_coins + A - 1) / A, 7); // 切り上げ処理 cout << weeks * 7 + nokori_days << endl; }