題目連結:
題目大意:
第一列給定兩正整數 n 、 k (1 ≦ n ≦ 100, 000,2 ≦ k ≦ n),代表有 n 隻鴿子,每隻有自己的分數值。
接下來的一列有 n 個正整數(皆介於 1 ~ 2, 147, 483, 647 之間),代表這 n 隻鴿子各自的分數值。
而 Boook 要從這 n 隻鴿子裡挑出一些鴿子,使得分數的總和為 k 的倍數。請輸出任意一組可能的挑法,先輸出挑的鴿子數,再接著輸出鴿子的編號(給定分數的順序);如果沒有任何可行的挑法,請輸出「0」。
輸出格式請參見範例輸出。
首先,證明不會有要輸出「0」的情況發生,也就是一定會有可行解:
定義 S0 = 0 ,而 Si = Si-1 + 第 i 隻鴿子的分數,也就是說 Si 代表著前 i 隻鴿子的分數總和。然後將 S0 、 S1 、 …… 、 Sn 取 k 的餘數。
因為 k ≦ n ,所以求除以 k 的餘數(模 k)之後, S0 ~ Sn 最多只會有 k 種可能的值(分別為0~ k -1)。
而因為 S0 ~ Sn 有 n + 1 項,根據鴿籠原理,因此我們可以得出在 S0 ~ Sn 這 n + 1 項之間必定會有兩項以上有相同的餘數(在模 k 下)。
而假設 Sa 、 Sb 兩項是其中一對餘數相同的兩項,則代表第 a + 1 隻 ~ 第 b 隻鴿子的分數和即為一組可能的解。( ∵ Sb - Sa ≡ 0 mod k,即代表 Sb - Sa 為 k 的倍數)
因此,絕對不會有要輸出「0」的情況發生。
而以上證明過程也提及了如何找出一組可能的解,因此達成了題目的要求。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。