[POI2007]砝碼Odw 貪心
阿新 • • 發佈:2018-12-09
Descripition 給你n個箱子,m個物品,問你最多能裝多少個物品,其中物品滿足任意兩個物品,他們中總有一個是另一個的整數倍。
Sample Input 2 4 13 9 4 12 2 4
Sample Output 3
這道題好神啊。。。 假設物品為{a1,a2,…,an},利用進位制拆分的思想。 對於一個箱子,你可將其拆分成k1a1+k2a2+…+knan這樣的一個式子,即變成一個n元組:{k1,k2,…,kn}。 然後你將每一個箱子箱子的n元組相加,然後從權值較低的物品開始判斷當前位置是否能填,不行你就向高位借一下位什麼的。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
LL s[110000];
int cnt, c[110000];
int a[110000], b[110000], belong[110000];
int main() {
int n = read(), m = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= m; i++) b[i] = read();
sort(b + 1, b + m + 1);
for(int i = 1; i <= m; i++) {
if(b[i] != b[i - 1 ]) c[++cnt] = b[i];
belong[i] = cnt;
}
for(int i = 1; i <= n; i++) {
for(int j = cnt; j >= 1; j--) if(a[i] >= c[j]){
int k = a[i] / c[j];
s[j] += k; a[i] -= k * c[j];
}
} int ans = 0, S = 0;
for(int i = 1; i <= m; i++) {
if(s[belong[i]]) ans++, s[belong[i]]--, S++;
else {
int k = belong[i];
while(k <= cnt && !s[k]) k++;
if(k > cnt) break;
for(int j = k - 1; j >= belong[i]; j--) {
s[j] += c[j + 1] / c[j]; s[j + 1]--;
} ans++; s[belong[i]]--;
}
} printf("%d\n", ans);
return 0;
}