切換
舊版
前往
大廳
主題

ZeroJudge - c548: Boook 愛鴿子 解題心得

Not In My Back Yard | 2019-04-13 23:25:04 | 巴幣 0 | 人氣 383

題目連結:


題目大意:
第一列給定兩正整數 n 、 k (1 ≦ n ≦ 100, 000,2 ≦ k ≦ n),代表有 n 隻鴿子,每隻有自己的分數值。

接下來的一列有 n 個正整數(皆介於 1 ~ 2, 147, 483, 647 之間),代表這 n 隻鴿子各自的分數值。

而 Boook 要從這 n 隻鴿子裡挑出一些鴿子,使得分數的總和為 k 的倍數。請輸出任意一組可能的挑法,先輸出挑的鴿子數,再接著輸出鴿子的編號(給定分數的順序);如果沒有任何可行的挑法,請輸出「0」。

輸出格式請參見範例輸出。



範例輸入:
5 3
7 92 47 5 1


範例輸出:
2
4 5


解題思維:
首先,證明不會有要輸出「0」的情況發生,也就是一定會有可行解:
定義 S = 0 ,而 S = Si-1 + 第 i 隻鴿子的分數,也就是說 S 代表著前 i 隻鴿子的分數總和。然後將 S 、 S 、 …… 、 S 取 k 的餘數。

因為 k ≦ n ,所以求除以 k 的餘數(模 k)之後, ~ S 最多只會有 k 種可能的值(分別為0~ k -1)。

而因為 ~ S 有 n + 1 項,根據鴿籠原理,因此我們可以得出在 S ~ S 這 n + 1 項之間必定會有兩項以上有相同的餘數(在模 k 下)。

而假設 S 、 S 兩項是其中一對餘數相同的兩項,則代表第 a + 1 隻 ~ 第 b 隻鴿子的分數和即為一組可能的解。( ∵ S - S ≡ 0 mod k,即代表 S - S 為 k 的倍數)

因此,絕對不會有要輸出「0」的情況發生。


而以上證明過程也提及了如何找出一組可能的解,因此達成了題目的要求。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

胖胖貓
單看題目覺得用 DFS 暴力法直接做感覺就是GG,看了一下討論區也覺得提出的 Cut-branch 也不是很可靠...
後來這題 icube 說到鴿籠原理才知道正確作法,題目給的條件 k ≦ n ,幾乎都很自然忽略。
2019-04-15 00:10:20
Not In My Back Yard
本人也是看到 icube 大大的提示,才想到這樣的解法XD
2019-04-15 00:36:23

相關創作

更多創作