洛谷 P1490 解題報告
P1490 買蛋糕
題目描述
野貓過生日,大家當然會送禮物了(咳咳,沒送禮物的同誌註意了哈!!),由於不知道送什麽好,又考慮到實用性等其他問題,大家決定合夥給野貓買一個生日蛋糕。大家不知道最後要買的蛋糕的準確價格,而只會給蛋糕估價,即要買一個不超過多少錢的蛋糕。眾OIer借此發揮:能否用最少的錢幣數去湊成估價範圍內的所有價值,使得不管蛋糕價值多少,都不用找錢……
現在問題由此引出:對於一個給定的n,能否用最少的不等的正整數去組成n以內(包括n)的所有的正整數呢?如果能,最少需要多少個正整數,用最少個數又有多少不同的組成方法呢?
輸入輸出格式
輸入格式:
只有一行包含一個整數n(1<=n<=1000)。
輸出格式:
一行兩個數,第一個數是最少需要多少個數,第二個數是用最少個數的組成方案個數。兩個答案用空格分隔。
- 首先明確第一個問題:這個最小的正整數是多少?
也許你可以打表看出來,也許不能,但別急,我們有看似靠譜一點的思維方法
看看樣例:6
可行方案:
①\(1\) \(2\) \(3\);
②\(1\) \(2\) \(4\).
我們發現,對於方案①,組成3的時候有兩種方法(1+2或3),而方案②只有一種。換而言之,3的利用是有浪費的。而不浪費的方案②還可以組成7。
那麽,我們咋讓她(每個數)都用好自己呢
很簡單,百合就行了
聯想一下二進制位下的數
\(1\),\(10\),\(11\)
可不是嘛,這個\(2^i\)的每個數利用率可高了
由此可知,二進制的位數即為這個最小的正整數。
- 想明白第一問以後,應該給出了一個相對的第二問的思維導向。(當然不絕對哈)
當每個數的利用率最大的時候,她們能夠湊成的最大整數即為她們的和,這點是毋庸置疑的。
那麽,在利用率相對不是那麽大的時候呢?
我們註意到,此時已經有了一個限制條件:已有的最小正整數
手動模擬一下,確實是仍然成立的。(其實是不太會證啦)
這時候,我們就把參與量已使用的各數之和和湊成的最大整數搞到一起去了
考慮\(dp[k]\)代表湊成時\(k\)的方案數。看看這時候還要壓哪些信息進去。
顯然,剩下的必要信息還有第\(i\)個數和第\(i\)個數的值\(j\)
\(dp[i][j][k]\)表示已選\(i\)個數,第\(i\)個數為\(j\),前\(i\)個數和為\(k\)(湊成的最大整數位\(k\))的時候的方案數
轉移方程 \(dp[i+1][l][k+l]+=dp[i][j][k];\)
其中\(l\)為枚舉的下一個填充數
核心代碼:
dp[1][1][1]=1;
for(int i=1;i<ans;i++)
for(int j=i;j<=(1<<(i-1));j++)
for(int k=i*(i-1)/2;k<(1<<i);k++)
for(int l=j+1;l<=k+1;l++)
if(l+k<=n)
dp[i+1][l][k+l]+=dp[i][j][k];
else
dp[i+1][l][n]+=dp[i][j][k];
註意\(j,k,l\)的上下界,都是被已經得到的第一問給約束住了
當然,也沒必要跑這麽死,比如\(k\)從\(i\)開始反而會快一些。
至於\(if\)和\(else\)的判斷,是為了方便求最後結果的一點點小貪心了。
2018.5.2
洛谷 P1490 解題報告