CJOJ1427 USACO NOV 不設找零

2022-03-29 09:02:57 字數 1284 閱讀 7436

fj正在市場上為他的農場採購日用品,他口袋裡有k(1<=k<=16)個硬幣,每乙個硬幣的面值均在1~1,000,000,000之間。fj有乙個包含n(1<=n<=100,000)種待購物品的序列清單,其中第i種物品需要的錢數為c(i),(1<=c(i)<=10,000),在購物的過程中,他隨時可以停下來用一枚硬幣付一次錢,每次付錢的物件為從上次付錢之後至當前所有物品價值和(當然,他所付的硬幣面值也必須足夠大),不巧的是,市場上的商戶們都沒有零錢了,因此如果fj給的硬幣面值大於所購物品價值,他也不會得到找零!

請計算fj完成n件物品的購物後,所能剩下的最大錢數。如果他無法買到所有物品,輸出-1。

第1行:兩個整數k,n;

第2~k+1行:每行為乙個硬幣面值;

第k+2~n+k+1行:這n行為fj所要購買的n件物品的價值。

一行,即結束購物後fj所剩餘的最大錢數,輸出-1表示他無法完成購物。

3 612

151063

3237

輸出解釋:

fj花費面值為10的硬幣購買前兩件物品,然後花費面值為15的硬幣購買剩餘的4樣物品,最後剩餘一枚面值為12的硬幣。

我們先想到既然k這麼小,可以壓狀態,對於每一枚硬幣都是取或者不取,然後就可以愉快的寫出如下一些東西:

設f[i]表示用i這個組合的硬幣對於上一次可以搞的最遠距離,g[i]表示用這個組合搞出來的最大剩餘.

然後就發現:f[i]可以用二分查詢優化更新,g[i]隨著更新就好了.

#include#include#include#include#include#include#includeusing namespace std;

#define ll long long

#define re register

inline int gi()

while(ch>='0' && ch<='9')

return sum*f;

}int k,n,sum[1000010],ar[1000010],coin[1000010],f[1000010],g[1000010],ans=-1;

int find(int from,int x)

else r=mid-1;

}return wz;

}int main()sum[n+1]=2147483647;

for(re int i=1;i<(1<<16);i++)

}if(f[i]==n && g[i]>ans)ans=g[i];

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

return 0;

}

CJOJ 免費航班

小z在moi比賽中獲得了大獎,獎品是一張特殊的機 票。使用這張機票,可以在任意乙個國家內的任意城市之間的免費飛行,只有跨國飛行時才會有額外的費用。小z獲得了一張地圖,地圖上有城市之間的飛機航班和 費用。已知從每個城市出發能到達所有城市,兩個城市之間可能有不止乙個航班。乙個國家內的每兩個城市之間一定有...

CJOJ 為了博多

做了個噩夢,夢見我的 n 把刀到60級會二次變身,變成乙個對推6圖有xi點貢獻,刷大阪城有yi點貢獻的刀,於是要把刀分成兩隊一隊刷大阪城另一隊推6圖 但是有m對兄弟刀在同一隊會有特殊的buff加成,加成值為wi,問怎樣分隊收益最大,最大值是多少。第一行兩個整數n 刀的數目 0 n 20000 m 兄...

CJOJ 1504 整數合併

現在給你一些連續的整數,它們是從 a 到 b 的整數。一開始每個整數都屬於各自的集合,然後你需要進行如下操作 每次選擇兩個屬於不同集合的整數,如果這兩個整數擁有大於等於 p 的公共質因子,那麼把他們所在的集合合併。反覆上述操作,直到沒有可以合併的集合為止。現在,小 x 想知道,最後有多少個集合。一行...