1. 程式人生 > >洛谷 P1490 解題報告

洛谷 P1490 解題報告

不用 不同 不同的 發揮 進制 i+1 ... 兩種方法 AS

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\)

,\(100\),\(101\),\(110\),\(111\),\(1000\)...

可不是嘛,這個\(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 解題報告