目次
A - Online Shopping
問題
N 種類の商品が売られているお店で商品を購入します。
i 種類目の商品は 1 個 $P_i$ 円で、 $Q_i$ 個購入しました。
購入時は送料が発生し、商品の合計金額が S 円以上なら 0 円、そうでないならば K 円かかります。
送料を含めた支払い額を求めてください。
制約
- $1≤N≤100$
- $1≤S≤10000$
- $1≤K≤10000$
- $1≤P_i≤10000$
- $1≤Q_i≤100$
- 入力はすべて整数
詳細はこちらです。
解説
商品の合計金額を求め、金額によって送料の加算処理を行います。
プログラム例
program abc332a
!P(N) :商品の値段
!Q(N) :商品の購入個数
!S :送料の無料ライン
!K :送料
!price:支払い金額
implicit none
integer i
integer N, S, K
integer, allocatable:: P(:), Q(:)
integer price
!入力
read (*, *) N, S, K
allocate (P(N), Q(N))
do i = 1, N
read (*, *) P(i), Q(i)
end do
!購入金額の計算
do i = 1, N
price = price + P(i)*Q(i)
end do
!送料の計算
if (price < S) price = price + K
!結果の出力
write (*, *) price
end program abc332a
B - Glass and Mug
問題
容量が G ml のグラスと、容量が M ml のマグカップが 1 つずつあります。
グラスとマグカップはいずれも空です。
以下の操作を K 回繰り返した後で、グラスとマグカップに水がそれぞれ何 ml ずつ入っているか求めてください。
各操作
- グラスが水で満たされているとき、すなわちグラスにちょうど G ml 入っているとき、グラスの水をすべて捨てる。
- マグカップが空であるとき、マグカップを水で満たす。
- マグカップが空になるかグラスが水で満たされるまで、マグカップからグラスに水を移す。
制約
- $1≤K≤100$
- $1≤G<M≤1000$
- G,M,K は整数
詳細はこちらです。
解説
指定の操作回数 K 回を満たすまで、前項で示した操作を行います。
プログラム例
program abc332b
!G :グラスの容量
!M :マグカップの容量
!current_G:現在グラスに入っている水の量
!current_M:現在マグカップ入っている水の量
!K :繰り返し回数
!cnt :現在の繰り返し回数
implicit none
integer G, M
integer current_G, current_M
integer K
integer cnt
!入力
read (*, *) K, G, M
current_G = 0; current_M = 0; cnt = 0
!水の移し替え
do
!グラスが満杯なら水を捨てる
if (current_G == G) then
current_G = 0
cnt = cnt + 1
if (cnt >= K) exit
end if
! マグカップが空なら水を入れる
if (current_M == 0) then
current_M = M
cnt = cnt + 1
if (cnt >= K) exit
end if
!マグカップからグラスに水を移す
select case (current_G)
case (0) !グラスが空
if (current_M > G) then !マグカップの残量がグラスの残量より多い
current_M = current_M - G
current_G = G
else !マグカップの残量がグラスの残量より少ない
current_G = current_M
current_M = 0
end if
case (1:) !グラスが空でない
if (current_M > G) then !マグカップの残量がグラスの残量より多い
current_M = current_M - (G - current_G)
current_G = G
else !マグカップの残量がグラスの残量より少ない
current_M = 0
current_G = current_G + current_M
end if
end select
cnt = cnt + 1
if (cnt >= K) exit
end do
write (*, '(i0,1x,i0)') current_G, current_M
end program abc332b
C - T-shirts
問題
A さんの N 日間の予定が 0, 1, 2 のみからなる長さ N の文字列 S で与えられます。
0, 1, 2 では以下の予定を消化します。
予定
0 何の予定も入っていません。
1 食事に行く予定があります。
2 競技プログラミングのイベントに行く予定が入っています。
予定を消化する際には、「無地の T シャツ」、「AtCoder のロゴ入りの T シャツ」を着る予定です。具体的に述べると、以下の方針に従ってシャツを着ていきます。
- 食事に行く日には、無地の T シャツ 1 枚またはロゴ入りの T シャツ 1 枚を着用する
- 競技プログラミングのイベントに行く日にはロゴ入りの T シャツ 1 枚を着用する。
- 何の予定もない日には T シャツを着用しない。加えてその時点で着用済みの T シャツを全て洗濯する。 洗濯したT シャツは翌日から着用できる。
- 一度着用した T シャツは次に洗濯するまで着用できない。
1 日目の時点で洗濯済みの無地の T シャツを M 枚持っている場合、予定を全て消化しきる場合にはロゴ入りの T シャツは何枚いるかを求めてください。
制約
- $1≤M≤N≤1000$
- S は 0, 1, 2 のみからなる長さ N の文字列
- N,M は整数
詳細はこちらです。
解説
予定0 が来れば着ることのできる T シャツの枚数リセットされます。
「予定0 で囲まれた範囲」で必要となる Tシャツの枚数の最大数を求めることで、購入すべきシャツの枚数を知ることができます。
プログラム例
program abc332c
!N :予定の日数
!M :無地のTシャツの所有枚数
!S :各予定の内容
!tmp_M:必要な無地Tシャツの枚数(暫定)
!tmp_T:必要なロゴTシャツの枚数(暫定)
!max_T:必要なロゴTシャツの最大数
implicit none
integer i
integer N, M
character(:), allocatable ::S
integer tmp_M, tmp_T, max_T
!入力
read (*, *) N, M
allocate (character(N)::S)
read (*, *) S
max_T = 0; tmp_T = 0; tmp_M = 0
!Tシャツの集計
do i = 1, N
select case (S(i:i))
case ("0") !予定なし(洗濯)
call wash_shirt(tmp_T, tmp_M, max_T, M)
tmp_T = 0; tmp_M = 0;
case ("1") !食事の予定
tmp_M = tmp_M + 1
case ("2") !プログラミングのイベント
tmp_T = tmp_T + 1
end select
end do
call wash_shirt(tmp_T, tmp_M, max_T, M)
!結果の出力
write (*, *) max_T
contains
subroutine wash_shirt(tmp_T, tmp_M, max_T, M)
!tmp_M:0で囲まれた区間で必要な無地Tシャツの枚数(暫定)
!tmp_T:0で囲まれた区間で必要なロゴTシャツの枚数(暫定)
!max_T:必要なロゴTシャツの最大数
!cnt_T:0で囲まれた区間で必要な無地Tシャツの枚数(確定)
!cnt_M:0で囲まれた区間で必要な無地Tシャツの枚数(確定)
!M :無地のTシャツの所有枚数
integer tmp_M, tmp_T, max_T, M
integer cnt_T, cnt_M
cnt_T = 0; cnt_M = 0
!無地Tの集計
if (tmp_M > M) then !無地Tの所持数より必要数が多い
cnt_T = tmp_M - M
cnt_M = 0
else !無地Tの所持数より必要数が少ない
cnt_M = M - tmp_M
cnt_T = 0
end if
!ロゴTの集計
cnt_T = cnt_T + tmp_T
!最大値の更新
if (max_T < cnt_T) max_T = cnt_T
end subroutine wash_shirt
end program abc332c