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;
}

 

posted @ 2017-09-16 22:01  cxhscst2  阅读(229)  评论(0编辑  收藏  举报