CF837D Round Subset

【刷题笔记】Round Subset

思路

考虑最朴素的可行性DP,设 fi,j,x,y 表示前 i 个数,选了 j 个数,其中有 x5 y2 时是否合法,但是枚举时间复杂度为 O(nknlog51018nlog21018)O(n3klog51018log21018)
考虑优化,将可行性 DP 改为最值 DPfi,j,k 表示前 i 个数, 选了 j 个,有 k52 的最大个数,因为 log2log5 大所以要优化掉 log2
得到转移方程

fi,j,k=max(fi1,j1,kcnt5i+cnt2i,fi,j,k)

发现还能用滚动数组优化掉一维,得到最后方程

fj,k=max(fj1,kcnt5i+cnt2i,fj,k)

注意初始化,要将 f 数组初始化为 INF 不然会出现一些不合法方案

Code

#include<bits/stdc++.h>
#define maxn 5010
#define ll long long
using namespace std;
ll n, K, cnt2[maxn], cnt5[maxn], a[maxn], f[210][maxn];
ll ans = 0, tot = 0;
int main(){
	cin >> n >> K;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		while(a[i] && a[i] % 2 == 0){
			++cnt2[i];
			a[i] /= 2;
		}
		while(a[i] && a[i] % 5 == 0){
			++cnt5[i];
			a[i] /= 5;
		}
		tot += cnt5[i];
	}
	memset(f, -0x3f, sizeof(f));
	f[0][0] = 0;
	for(int i = 1; i <= n; i++){
	 	for(int j = K; j >= 1; j--){
			for(int k = cnt5[i]; k <= tot; k++){
				f[j][k] = max(f[j][k], f[j - 1][k - cnt5[i]] + cnt2[i]);
			}
		}
	}
	for(ll i = 1; i <= tot; i++){
		ans = max(ans, min(f[K][i], i));
	}
	cout << ans;
	return 0;
}
posted @   GuoSN0410  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示