在今天的模擬賽中,部分同學由於對出現某個數在模 \(1000000007\) 意義下為 \(0\) 的情況不規範被 Hack。
Hack 原理:開始時有 \(2\) 個 \(1\),先都加到 \(1000000001\),然後一個一個加 \(8\) 次雖然加 \(7\) 次足以 Hack,這個時候如果對 \(1000000007\) 處理不好,可能後面都變成 \(0\)。
我的方案:考慮兩個性質(按照題解):
- \(2\) 操作到 \(1000000007\) 的倍數(分子為 \(0\))只可能是 \(1000000007\),也就是說每個位置至多出現一次分子或分母為 \(0\)。
- 分母為 \(0\) 的上一步同樣位置的 \(2\) 操作中一定分子為 \(0\),因為分母為 \(0\) 時必定出過 \(a_i=1000000007\)。(我可能給之前的同學解釋錯了,因為可能出現 \(3\) 操作使得分子分母為 \(0\) 的 \(2\) 操作之間夾著幾個,但也無傷大雅,這裡致以誠摯歉意)。
綜上所述,考慮記錄每個位置上一次的分子為 \(0\) 位置,維護一個指標指向當前更新到的點。遇到分子為 \(0\) 的值,停止維護,輸出答案一定為 \(0\)。遇到分母為 \(0\),找到對應分子為 \(0\) 的位置,合併兩個分數:將後者的分子賦給前者,後者置為 \(1\),這樣保證後面的值都是對的。指標繼續往下跳轉,直到遇到下一個分子為 \(0\) 的數。
以 Hack 資料為例,最後幾個數為 \(\frac{0}{1000000006},\frac{0}{1000000006},\frac{1}{0},\frac{1}{0}\cdots\),位置分別在 \(1,2,1,2\cdots\),掃到第一、二個數停止更新,輸出 \(0\)。掃到第三個數,將第一個數變成 \(\frac{1}{1000000006}\),第三個數變為 \(1\),往下更新到第二個數處。掃到第四個數,同理更新,此時可以更新到第四個數。
附:資料,我的程式碼