A - 屋台の営業日数 / Number of Days a Food Stall Is Open Editorial by admin
Claude 4.6 Opus (Thinking)概要
屋台の1日あたりの収支(売上 − 日給の合計)を求め、それが黒字か赤字かで場合分けし、赤字の場合は所持金が尽きるまでの最大日数を計算する問題です。
考察
まず、1日の営業で所持金がどう変化するかを整理しましょう。
- 1日の売上: 全商品の人気度の合計 \(\displaystyle\sum_{i=1}^{N} A_i\)
- 1日の支出: 全アルバイトの日給の合計 \(\displaystyle\sum_{j=1}^{M} B_j\)
- 1日あたりの収支(利益): \(P = \displaystyle\sum_{i=1}^{N} A_i - \sum_{j=1}^{M} B_j\)
\(d\) 日営業した後の所持金は以下のようになります:
\[S + d \times P\]
場合分け
場合1: \(P \geq 0\) のとき(利益がゼロ以上)
毎日の営業で所持金が減らない(増えるか変わらない)ため、何日でも営業を続けられます。答えは -1 です。
場合2: \(P < 0\) のとき(毎日赤字)
1日あたり \(|P|\) 円ずつ所持金が減っていきます。\(d\) 日後に所持金が \(0\) 以上であるための条件は:
\[S + d \times P \geq 0\]
\[S - d \times |P| \geq 0\]
\[d \leq \frac{S}{|P|}\]
\(d\) は整数なので、最大日数は \(\left\lfloor \dfrac{S}{|P|} \right\rfloor\) です。
具体例
例えば \(N=2, M=2, S=10, A=[3, 5], B=[4, 6]\) のとき:
- 売上合計 \(= 3 + 5 = 8\)
- 日給合計 \(= 4 + 6 = 10\)
- 1日あたりの損失 \(= 10 - 8 = 2\) 円
最大日数 \(= \lfloor 10 / 2 \rfloor = 5\) 日です。実際に確認すると、5日後の所持金は \(10 + 5 \times (-2) = 0\) 円で、ちょうど \(0\) 円なのでOKです。
アルゴリズム
- 配列 \(A\) の合計(売上)と配列 \(B\) の合計(日給)を計算する。
- 1日あたりの利益 \(P = (\text{売上}) - (\text{日給})\) を求める。
- \(P \geq 0\) なら
-1を出力する。 - \(P < 0\) なら \(\left\lfloor S / |P| \right\rfloor\) を出力する。
計算量
- 時間計算量: \(O(N + M)\)(配列の合計を求めるだけ)
- 空間計算量: \(O(N + M)\)(入力の格納)
実装のポイント
\(S\) の上限が \(10^{18}\)、\(A_i, B_j\) の上限が \(10^9\) で、それぞれ最大 \(10^5\) 個あるため、合計値は最大 \(10^{14}\) 程度になります。Python は多倍長整数を扱えるのでオーバーフローの心配はありませんが、C++ などで実装する場合は
long long型を使う必要があります。\(P = 0\) のとき(売上と日給がちょうど等しいとき)も、所持金は減らないため無限に営業でき、
-1を出力します。この場合を見落とさないよう注意しましょう。Python の整数除算
//は負の無限大方向への切り捨てですが、ここでは \(S \geq 0\) かつ \(|P| > 0\) なので通常の切り捨て除算と一致し、問題ありません。ソースコード
def main():
import sys
input_data = sys.stdin.read().split()
idx = 0
N = int(input_data[idx]); idx += 1
M = int(input_data[idx]); idx += 1
S = int(input_data[idx]); idx += 1
A = []
for i in range(N):
A.append(int(input_data[idx])); idx += 1
B = []
for i in range(M):
B.append(int(input_data[idx])); idx += 1
total_sales = sum(A)
total_wages = sum(B)
daily_profit = total_sales - total_wages
if daily_profit >= 0:
# Each day we gain or break even, so we can operate forever
print(-1)
else:
# daily_profit < 0, so each day we lose (-daily_profit) yen
# After d days: S + d * daily_profit >= 0
# S + d * daily_profit >= 0
# d <= S / (-daily_profit)
loss_per_day = -daily_profit
print(S // loss_per_day)
main()
この解説は claude4.6opus-thinking によって生成されました。
posted:
last update: