各クエリに対して愚直に掛け算をしていく場合、計算量は となってしまい、間に合いません。 ここで、各クエリをより高速に処理する方法を考えます。
ある数列の連続する部分列の総和を高速に処理するアルゴリズムとして累積和が有名ですが、この問題ではその応用として累積積を用います。
具体的には、
を満たす数列 をあらかじめ計算しておくことで、求める値を
として求めることができます。
ここで問題となるのがあまりです。この問題は、モジュラ逆数(通称逆元)という概念を用いることで解決できます。(逆元の求め方は長くなるので割愛)
累積和アルゴリズムと同様に、前処理が 、クエリの計算に 、合わせて でこの問題を解くことができます。
(逆元は、合同式の法 の大きさに関して対数時間で求められるため、 と決まっているこの問題では とみなすことができます。)
セグメント木を用いると、 で求めることができます。