完全揹包 NOIP2018 貨幣系統

2022-09-03 01:51:12 字數 1683 閱讀 6539

在網友的國度中共有\(n\)種不同面額的貨幣,第\(i\)種貨幣的面額為\(a[i]\),你可以假設每一種貨幣都有無窮多張。為了方便,我們把貨幣種數為\(n\)、面額陣列為\(a[1..n]\)的貨幣系統記作\((n,a)\)。

在乙個完善的貨幣系統中,每乙個非負整數的金額\(x\)都應該可以被表示出,即對每乙個非負整數\(x\),都存在\(n\)個非負整數\(t[i]\)滿足\(a[i] \times t[i]\)的和為\(x\)。然而, 在網友的國度中,貨幣系統可能是不完善的,即可能存在金額\(x\)不能被該貨幣系統表示出。例如在貨幣系統\(n=3,a=[2,5,9]\)中,金額\(1,3\)就無法被表示出來。

兩個貨幣系統\((n,a)\)和\((m,b)\)是等價的,當且僅當對於任意非負整數\(x\),它要麼均可以被兩個貨幣系統表出,要麼不能被其中任何乙個表出。

現在網友們打算簡化一下貨幣系統。他們希望找到乙個貨幣系統\((m,b)\),滿足\((m,b)\)與原來的貨幣系統\((n,a)\)等價,且\(m\)盡可能的小。他們希望你來協助完成這個艱鉅的任務:找到最小的\(m\)。

輸入格式:

輸入檔案的第一行包含乙個整數\(t\)表示資料的組數。

接下來按照如下格式分別給出\(t\)組資料。 每組資料的第一行包含乙個正整數\(n\)。接下來一行包含\(n\)個由空格隔開的正整數 \(a[i]\)。

輸出格式:

輸出檔案共有\(t\)行,對於每組資料,輸出一行乙個正整數,表示所有與\((n,a)\)等價的貨幣系統\((m,b)\)中,最小的\(m\)。

2

43 19 10 6

511 29 13 19 17

2

5

我們先證明乙個結論:

那麼要使\(m\)最小,\((m,b)\)中的每乙個元素必定存在於\((n,a)\)中

下面給出這個結論的證明:

假設\((m,b)\)中包含乙個不存在於\((n,a)\)中的元素

則有兩種情況:

這個元素可以被\((n,a)\)中的元素表示,那麼此時\(m\)不滿足最小,因為這個元素可以被剔除

這個元素不能被\((n,a)\)中的元素表示,那麼此時不滿足\((n,a)\)與\((m,b)\)等效

所以\((m,b)\)中不包含任何不存在於\((n,a)\)中的元素

那麼我們就可以直接從\((n,a)\)中剔除可以被自己表示的元素就可以得到\((m,b)\)了

只需要揹包一下就行了,思路還是很清晰的

上**:

#includeusing namespace std;

const int maxn=30001;

int n,ans,t,maxn=0,a[maxn],vis[maxn];

bool tf[maxn],dp[maxn];//tf[i]表示數字i是否出現在(n,a)中

//dp[i]表示數字i是否可以被(n,a)表示

int main()

sort(a+1,a+1+n);

dp[0]=true;

for(int i=a[1];i<=maxn;i++)else//否則用它來表示其他的數值}}

printf("%d\n",ans);

}}

NOIP2018 貨幣系統

我們發現這個新的系統的貨幣一定是都屬於原來的集合內的,所有我們只需要判斷原來的數能不能被其他的數替代。然後我們自然就有一種想法就是從小到大找。這個時候如果這個數無法被替代,那麼這個數一定會被選中,如果能被替代就不要了。而從小到大正好可以避免漏選的情況,我們發現a ia i ai 都比較小,我們就可以...

2018NOIP提高組 貨幣系統(完全揹包)

貨幣系統 在的國度中共有 n 種不同面額的貨幣,第 i 種貨幣的面額為 a i 你可以假設每一種貨幣都有無窮多張。為了方便,我們把貨幣種數為 n 面額陣列為 a 1.n 的貨幣系統記作 n,a 在乙個完善的貨幣系統中,每乙個非負整數的金額 x 都應該可以被表示出,即對每乙個非負整數 x,都存在 n ...

NOIp2018提高組 貨幣系統

有 n n le100 種不同的貨幣,每種貨幣的面額為 1,25000 之間的乙個整數。若兩種貨幣系統能夠組合出來的數是相同的的,那我們就稱這兩種貨幣系統是等價的。給定乙個貨幣系統,求不同面額貨幣數最少的等價的貨幣系統。將面額從小到大排序,如果一種面額能夠被其它面額表示出來,那麼這種面額就是多餘的。...