ABC466 F - Many Mod Calculation

連続剰余

考え方

$1$ 以上 $X$ 以下の全ての数に対して処理を行ったときに、どういう値が何個あるのか持てばよい。
もちろん、愚直にやっては $O(X)$ 個の情報をもつことになって、計算量もメモリも足らない。

そこで、特殊な圧縮をしてデータを持つことにする。
つまり、「$0$ 以上 $k$ 未満の値が $1$ つずつある」みたいな形で持つ。
すると、このカタマリを A[i] で割った余りも、類似の形式複数個で表現できる。
具体的には、「$0$ 以上 $k$ 未満の値が $l$ 個ずつある」データを $a$ で割る場合は、以下。

あとはこれを、同じ範囲のものは可能な限りデータをまとめていく工夫をすればよい。
範囲が A[i] を超えるものの抽出は、priority_queue などを用いればよい。

与えられる問題は $0$ 以上ではなく $1$ 以上であるため、そこだけ困ったように見える。
が、「$0$ 以上 $1$ 未満の値が $-1$ 個ずつある」を入れておくことで解消できる。
しかも、これが番兵として機能してくれるため、コード的にも都合がいい。

計算量の見積もりは非常に難しいが、中途半端な長さのデータは最大でも $O(N)$ 個しか出てこない。
また、$1$ つのデータの幅は、剰余を $1$ 回とられるたびに半分未満になる。
これらのことから、全体で $O(N \log N \log X)$ であるため、間に合う。

入力例1での動作

$1$ つめのテストケースのみ。

入力を受け取る。

n: 3
x: 7
a: {5, 2, 3}

最初に、[0,8) を $1$ 個、[0,1) を $-1$ 個入れる。
これにより、整数 $1$ 以上 $7$ 以下が $1$ 個ずつある状態を表す。

[0,8): 1個
[0,1): -1個

a[0]=5 で余りを取る。

[0,8) は、[0,5) が $1$ 個と、端数の [0,3) が $1$ 個に分かれる。
[0,1) は上限が $5$ 以下なので変化しない。

[0,5): 1個
[0,3): 1個
[0,1): -1個

a[1]=2 で余りを取る。

[0,5) は、[0,2) が $2$ 個と、端数の [0,1) が $1$ 個に分かれる。
[0,3) は、[0,2) が $1$ 個と、端数の [0,1) が $1$ 個に分かれる。

同じ区間をまとめると、次のようになる。

[0,2): 3個
[0,1): 1個

a[2]=3 で余りを取る。
すべての区間の上限が $3$ 以下なので、状態は変化しない。

[0,2): 3個
[0,1): 1個

すべての区間には 0 が $1$ 個ずつ含まれる。
よって、区間の個数の合計が答えになる。

result: 3+1
      = 4

注意点

$X$ や $A_i$ は、int 型からはみ出る。
long long 型を用いること。

別解

特になし。