題目連結:
題目大意:
給你N個骰子,試問擲出M點(N ≦ M ≦ 6N)的方法數為多少?
解題思維:
典型的動態規劃(DP)題。
首先觀察以下附圖:
仔細觀察,我們便可以發現到為什麼2個骰子擲出4點方法數為3、3個骰子擲出6點的方法數為10等等。
我們很直覺的就可以知道當只有一個骰子時,擲出各點數的方法數(皆為1)。
那兩個骰子呢?很簡單,對於擲出「4點」來說,它是第一顆骰子擲出1點,然後第二顆骰子擲出3點;或是第一顆擲出2,第二顆擲出2;又或是第一顆為3,第二顆為1。
再看看3顆骰子擲出6點時,讓我們以(a, b)的a表示前兩顆骰子的點數總和,b表示第三顆骰子擲出的點數。結果有:(2, 4)、(3, 3)、(4, 2)、(5, 1)。又因為兩顆骰子擲出2、3、4、5點的方法數分別為1、2、3、4種,所以總共是10種。
也就是說,N個骰子擲出M點的方法數可以表達為(N-1)個骰子擲出M-1的方法數+(N-1)個骰子擲出M-2的方法數+……+(N-1)個骰子擲出M-6的方法數。(因為第N顆骰子可以擲出1~6的點數)
上面的規則也就是可以作為DP的依據(遞迴也可以,但是在這題我想要「預處理」)。
但由於DP的過程中會產生C++中的long long存不下的狀況。因此要寫一個大數,要去做大數加法。作法可參考這裡。2019 / 3 / 5 日更正:不會超過 long long 可儲存範圍,可以安心使用。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。