いくつかのステップに分けて書いているので、分からない時は一つだけ読んでまた考えるのも良いと思います。
確率論において、確率変数の期待値(きたいち、英: expected value)とは、確率変数のすべての値に確率の重みをつけた加重平均である。 (期待値 - Wikipadia より)
求める期待値は 商品が 個開封される確率 商品が 個開封される確率 商品が 個開封される確率 という和になります。
Moja くんが注文した商品が一つのみであるとき、その商品が開封されてしまう確率を とすると開封されてしまう商品の個数の期待値は
商品が 個開封される確率 商品が 個開封される確率
より、商品が開封される確率そのものになります。
Moja くんが複数の商品を注文しているときは各商品について「Moja くんがその商品しか注文しなかった場合」を考えてそれぞれの場合での期待値を合計すれば問題の答えが求まります。よって、Moja くんが注文したそれぞれの商品に対し開封されてしまう確率を計算して合計すれば答えとなります。
Moja くんが注文した商品を一つ選び、その重量を とします。その商品が開封される確率を求めるために を全走査して を計算すると の時間計算量が掛かってしまい、 から までの全ての に対してこれを行うと の時間計算量が掛かってしまうため、2 秒間の実行時間制限に間に合いません。しかし Moja くんの注文した商品を一つずつ見て確率を求めていくことは避けられなさそうです。では、そこは仕方ないとして、各商品が開封される確率を の時間を掛けずに求めることはできないでしょうか。
商品の重量を並べる順番は答えに関係しないので、与えられた重量はそれぞれソートすることができます。
整数の比較やコピー等の操作に掛かる時間が であることを仮定すると、時間計算量
お母さんが商品を開封する確率に含まれる は Moja くんが頼んだ商品の重量 とお母さんが頼んだ商品 の「近さ」を表しています。例えば と の差 がとても小さいとき は に近くなるため、それを から引いた値は に近くなります。
そこで、 の値は に近い を見るだけで計算できそうです。
与えられた と は昇順にソートしておきます。すると各 に対して が最大となる は広義単調増加します。例えば に一番「近い」商品が であったとき、次に に一番「近い」商品を探すために から まで を候補に入れる必要はありません。よって の配列を全走査しつつ「 の配列を今どこまで見たか」という値も持っておくことで、 の時間計算量を避けることができます。
以下の擬似コードの内容を実装します。
の配列も の配列も前から後ろまで一度しか走査されないのでループの部分の時間計算量は です。配列をソートする必要があるため、全体の時間計算量は となります。