一些转移细节还不太清楚的线性dp
D. Round Subset
老早写过了,但是边界考虑不太清楚
https://codeforces.com/problemset/problem/837/D
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 205, M = 30 * 200;
int n, k, ans, t2[N], t5[N], f[2][N][M]; //f[i][j]: 选了i个, 5的值为j的最大2的个数
int main () {
scanf ("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
ll x;
scanf ("%lld", &x);
while (x && x % 2 == 0) t2[i]++, x /= 2;
while (x && x % 5 == 0) t5[i]++, x /= 5;
//cout << t2[i] << ' ' << t5[i] << endl;
}
memset (f, -1, sizeof f);
f[0][0][0] = f[1][0][0] = 0;
for (int ii = 1; ii <= n; ii++) {
int t = ii & 1, tt = t ^ 1;
for (int i = 0; i <= min (ii, k); i++) { //i之前选了多少
for (int j = 0; j <= 30 * i; j++) { //之前有多少个5
if (!i || j < t5[ii] || f[t][i - 1][j - t5[ii]] == -1) continue;
f[tt][i][j] = max (f[tt][i][j], f[t][i - 1][j - t5[ii]] + t2[ii]);
}
}
//记得滚过来
for (int i = 0; i <= min (ii, k); i++) {
for (int j = 0; j <= 30 * i; j++) {
f[t][i][j] = f[tt][i][j];
}
}
}
for (int i = 0; i <= 30 * n; i++) ans = max (ans, min(f[n & 1][k][i], i));
cout << ans << endl;
//cout << log (1e18) / log (5);
}