BZOJ 3233 找硬幣(貪心 動態規劃)

2021-07-25 02:39:25 字數 1693 閱讀 8693

題目:

description

小蛇是金融部部長。最近她決定製造一系列新的貨幣。假設她要製造的貨幣的面值為x1,x2,x3… 那麼x1必須為1,xb必須為xa的正整數倍(b>a)。例如1,5,125,250就是一組合法的硬幣序列,而1,5,100,125就不是。不知從哪一天開始,可愛的蛇愛上了一種萌物——兔紙!從此,小蛇便走上了遇上兔紙娃娃就買的不歸路。某天,小蛇看到了n只可愛的兔紙,假設這n 只兔紙的價錢分別是a1,a2…an。現在小蛇想知道,在哪一組合法的硬幣序列下,買這n只兔紙所需要的硬幣數最少。買兔紙時不能找零,1<=n<=50, 1<=ai<=100,000

input

第一行,乙個整數n,表示兔紙的個數

第二行,n個用空格隔開的整數,分別為n只兔紙的價錢

output

一行,乙個整數,表示最少付的錢幣數。

sample input

2 

25 102

sample output

4

hint

樣例解釋:共有兩隻兔紙,價錢分別為25和102。現在小蛇構造1,25,100這樣一組硬幣序列,那麼付第一只兔紙只需要乙個面值為25的硬幣,第二隻兔紙需要乙個面值為100的硬幣和兩個面值為1的硬幣,總共兩隻兔紙需要付4個硬幣。這也是所有方案中最少所需要付的硬幣數。

這是乙個貪心+動態規劃問題

關於貪心比較好理解,在給定硬幣序列的情況下,盡量使最大的硬幣使用最多,然後再盡量使第二大的硬幣使用最多,等等。。。

這種貪心策略,只在本題條件下成立,對於一般的硬幣序列就不一定了。

動態規劃就比較有趣了。

用dp[i]表示在最大的硬幣為i的情況下,最少需要付的硬幣數

那麼dp[j]是滿足i|j的所有i中,f(i,j)的最小值

其中,f(i,j)表示的是最大硬幣為j,第二大的硬幣為i時,最少需要付的硬幣數,可以根據dp[i]直接求出來。

這樣就得到了遞推式,可以動態規劃了,不過超時了。

於是上面的演算法還可以優化:

dp[j]是滿足i|j的所有i中,f(i,j)的最小值,這一點無疑是對的,但是還不夠簡單。

實際上,dp[j]是滿足j=i*p(p為任意素數)的所有i中,f(i,j)的最小值

這樣,計算可以變快,不過需要預先給出素數表。

我用的方法是篩法打表,把素數按順序存到pri陣列中

**:

#include

using namespace

std;

int num[

50], dp[

100001

], prime[

100001

], pri[

10000

];int

main

()for

(int i =

1; i <= m; i++)prime[i]=1

;for

(int i =

2; i <= m; i++)

if(prime[i])

for(

int i =

2; i <= m; i++)dp[i]

=12345678

;for

(int i =

1; i <= m; i++)

} cout << result << endl;

return0;

}

BZOJ1002(找規律 大數)

time limit 1 sec memory limit 162 mb submit 2427 solved 1333 submit status 給定n n 100 程式設計計算有多少個不同的n輪狀病毒。第一行有1個正整數n。將程式設計計算出的不同的n輪狀病毒數輸出 316 題意 rt 思路 d...

bzoj4566 找相同字元

題意 給定兩個字串,從中各取乙個子串使之相同,有多少種取法。允許本質相同。解 建立廣義字尾自動機,對於每個串,分別統計cnt,之後每個點的cnt乘起來。記得開long long 1 include 2 include 3 include 4 5 typedef long long ll 6 cons...

BZOJ4264 小C找朋友

description 幼兒園裡有n個小c,兩個小c之間可能是朋友也可能不是。所有小c之間的朋友關係構成了乙個無向圖,這個無向圖中有m條邊。園長atm發現對於兩個 不同的 小ci和j,如果其他的所有小c要麼同時是i,j的朋友,要麼同時不是i,j朋友的話,這兩個小c就很有可能一起去吃飯,成為一對好友。...