Codeforces 837D Round Subset(背包)
阿新 • • 發佈:2017-09-17
邊界 efi set test blog 個數 復雜度 names 預處理
題目鏈接 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; }
Codeforces 837D Round Subset(背包)