累積和は、「適切な前処理をおこない、配列上の区間の総和を高速で処理できるようにする手法」です。累積和を利用することで配列上の区間の総和がどれくらい速く計算できるようになるのかを検証します。

区間の和を求める

第一問

https://paiza.jp/works/mondai/prefix_sum_problems/prefix_sum_problems__section_sum_step1

10 個の整数 a_0, a_1, a_2, …, a_9 からなる数列 a が与えられるが、この数列の a_2 から a_7 までの和はどうなるだろうか?

累積和をつかわず普通にa[2]からa[7]までを足したほうが速そうですが、累積和を使うとこうなります。当然のことながら計算結果は同じになります。

これだけだとあまり便利さがわかりません。普通に計算したほうが速そうです。

ではこれだとどうでしょうか?

連続する3つの数の和を取得する

https://paiza.jp/works/mondai/prefix_sum_problems/prefix_sum_problems__sum_max_step1

i番目までの総和から(i-3)番目までの総和を引くことでる3つの数の和を知ることができます。高校の数学で自然数の総和の公式を習いますが、1からではなく途中の数からの場合、(bまでの総和)-(aまでの総和)で(a+1)からbまでの総和を求めることができます。似たような方法をここで使います。

System.Diagnostics.Stopwatchをつかって実行時間を計測していますが、両者ほとんど変わりません。

連続するk個の和

こんな問題もあります。

https://paiza.jp/works/mondai/prefix_sum_problems/prefix_sum_problems__sum_max_boss

問題の条件で「配列の大きさは最大で100」ですが、これではあまり違いはわかりません。

しかし連続するk個の和で最大のものを求める場合で、最初の配列が長く、しかもkの値が大きいとどうなるでしょうか? ここからは管理人の自由研究です。

巨大な配列

まず乱数を発生させるメソッドをつくります。乱数だと生成される値で計算にかかる時間に差ができてしまうかもしれないので0~9までの値しか生成されないようにします。

長く連続するk個の数の和

比較のためにふたつのメソッドを作成します。Test1は累積和を利用して連続するk個の数の和を取得し、Test2は普通の方法で連続するk個の数の和を取得します。

結果はいかに?

これで実行時間を比較します。どのようなPCを使うかで結果はかわりますが、ここまで極端なことをすると大きな差になりました。累積和を使えば0.1秒程度で終わりますが、使わないと6秒もかかります。約60倍の違いです。

何度も計算を繰り返す場合は累積和を利用したほうが効率よく結果を取得することができます。