題目的難度顏色使用 Luogu 上的分級,由簡單到困難分別為 🔴🟠🟡🟢🔵🟣⚫。
Problem Statement
題目簡述
給定長度為 n n n 的序列:每個位置 i i i 有數值 a i a_i a i 與顏色 c i c_i c i 。
考慮所有位置的三元組 ( x , y , z ) (x, y, z) ( x , y , z ) (1 ≤ x < y < z ≤ n 1 \le x < y < z \le n 1 ≤ x < y < z ≤ n )且滿足 y − x = z − y y-x=z-y y − x = z − y (等差),並且 c x = c z c_x=c_z c x = c z 。
對每個符合條件的三元組,貢獻為 ( x + z ) ⋅ ( a x + a z ) (x+z)\cdot(a_x+a_z) ( x + z ) ⋅ ( a x + a z ) ,求所有貢獻總和對 10007 10007 1 0 0 0 7 取模的結果。
Constraints
約束條件
1 ≤ n ≤ 100000 1 \le n \le 100000 1 ≤ n ≤ 1 0 0 0 0 0
1 ≤ a i ≤ 10000 1 \le a_i \le 10000 1 ≤ a i ≤ 1 0 0 0 0
1 ≤ c i ≤ m 1 \le c_i \le m 1 ≤ c i ≤ m (m m m 為顏色種類數)
取模:10007 10007 1 0 0 0 7
思路:貢獻法 + 分組前綴和
題目看起來在枚舉三元組 ( x , y , z ) (x,y,z) ( x , y , z ) ,但真正出現在公式中的只有 x , z x,z x , z ;中間點 y y y 只用來限制「x , z x,z x , z 之間必須能形成等差」。
1) 先把條件化成「可配對」
由 y − x = z − y y-x=z-y y − x = z − y 可得:
2 y = x + z 2y=x+z
2 y = x + z
因為 y y y 必須是整數位置,所以 x + z x+z x + z 必須是偶數,等價於:
x x x 與 z z z 的奇偶性相同(同為奇數或同為偶數)。
另外題目要求 c x = c z c_x=c_z c x = c z ,因此任何有效三元組都對應到一個「同顏色 + 同奇偶」的配對 ( x , z ) (x,z) ( x , z ) (且 x < z x<z x < z ),而中間點 y y y 由 y = ( x + z ) / 2 y=(x+z)/2 y = ( x + z ) / 2 唯一決定。
於是可以把所有位置依照「顏色」與「位置奇偶」分組;同一組內任取兩個不同位置 ( x , z ) (x,z) ( x , z ) 都能形成一個合法三元組(配對一次)。
2) 把每一組的總貢獻拆開計算
對於同一組中的一對 ( x , z ) (x,z) ( x , z ) (x < z x<z x < z ),貢獻是:
( x + z ) ( a x + a z ) (x+z)(a_x+a_z)
( x + z ) ( a x + a z )
展開後:
x a x + z a z + x a z + z a x x a_x + z a_z + x a_z + z a_x
x a x + z a z + x a z + z a x
可以把它理解成兩種部分:
每個元素的自項 :x a x x a_x x a x 與 z a z z a_z z a z
每個位置會和同組內其它 m − 1 m-1 m − 1 個位置配對,因此自項總和就是
∑ t ∈ group ( t ⋅ a t ) ⋅ ( m − 1 ) \sum_{t\in\text{group}} (t\cdot a_t)\cdot (m-1)
t ∈ group ∑ ( t ⋅ a t ) ⋅ ( m − 1 )
交叉項 :x a z + z a x x a_z + z a_x x a z + z a x
這部分可以用「枚舉右端點、維護左端點前綴」:
當掃描到目前位置 z z z 時,所有在它左邊的 x x x 都會貢獻
∑ x < z ( x ⋅ a z + z ⋅ a x ) = a z ⋅ ∑ x < z x + z ⋅ ∑ x < z a x \sum_{x<z} (x\cdot a_z + z\cdot a_x)= a_z\cdot\sum_{x<z}x + z\cdot\sum_{x<z}a_x
x < z ∑ ( x ⋅ a z + z ⋅ a x ) = a z ⋅ x < z ∑ x + z ⋅ x < z ∑ a x
所以只要在每組維護兩個前綴和:
左側位置編號總和 ∑ x \sum x ∑ x
左側數值總和 ∑ a x \sum a_x ∑ a x
每加入一個新元素,就能在 O ( 1 ) \mathcal{O}(1) O ( 1 ) 更新交叉項並累加答案。
複雜度分析
時間複雜度:O ( n ) \mathcal{O}(n) O ( n )
空間複雜度:O ( n ) \mathcal{O}(n) O ( n )
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from collections import defaultdictMOD = 10007 def solve (): n, m = map (int , input ().split()) A = list (map (int , input ().split())) C = list (map (int , input ().split())) assert len (A) == len (C) == n groups = defaultdict(list ) for i, (x, c) in enumerate (zip (A, C)): groups[(c, i & 1 )].append((i + 1 , x)) ans = 0 for g in groups.values(): m = len (g) s1 = s2 = 0 for a, b in g: ans += a * b * (m - 1 ) ans += a * s2 + b * s1 ans %= MOD s1 += a s2 += b print (ans) if __name__ == "__main__" : solve()