Codeforces 837D Round Subset(背包)
题目链接 Round Subset
题意 在n个数中选择k个数,求这k个数乘积末尾0个数的最大值。
首先我们预处理出每个数5的因子个数c[i]和2的因子个数d[i]
然后就可以背包了。
设f[i][j]为选i个数,5的因子总和为j时,2的因子总和的最大值。
则状态转移方程为 $f[i][j] = max(f[i - 1][j - c[k]] + d[k])$
注意边界条件
时间复杂度$O(5200nk)$
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
const int N = 210;
int n, k, m;
LL a[N];
int b[N];
int f[N][6010];
int ans = 0;
int c[N], d[N];
int main(){
scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%lld", a + i);
rep(i, 1, n){
for (; a[i] % 2 == 0; a[i] /= 2) ++d[i];
for (; a[i] % 5 == 0; a[i] /= 5) ++c[i];
}
rep(j, 0, m) rep(k, 0, 5200) f[j][k] = -(1 << 30);
f[0][0] = 0;
rep(i, 1, n){
dec(j, m, 1){
rep(k, c[i], 5200) f[j][k] = max(f[j][k], f[j - 1][k - c[i]] + d[i]);
}
}
rep(j, 0, 5200) ans = max(ans, min(f[m][j], j));
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号