cf837D(01背包)
2024-08-28 22:27:26
题目链接: http://codeforces.com/contest/837/problem/D
题意: 给出 n 个数, 从中选出 k 个数使得这 k 个数的乘积末尾 0 最多 .
思路: 先记录每个数能分解出的 2 和 5 的数目, 然后弄个01背包即可 .
用 dp[i][j][l] 表示从前 i 个数中选出 j 的数其中 5 的个数为 l 个的情况下 2 的数目最多是多少 .
初始状态为 dp[0][0][0] = 0, 推到终态 dp[n][k][MAX] 即可 . 注意要存在上一种状态才能到达下一种状态 .
然而开三维会 mle, 可以优化一下空间, 去掉 i 这维 .
状态转移方程式: if(dp[j - 1][l - gel[i].y] != -1) dp[j][l] = max(dp[j][l], dp[j - 1][l - gel[i].y] + gel[i].x); //注意判断上一种状态是否存在
代码:
#include <iostream>
#include <string.h>
#include <math.h>
#define ll long long
using namespace std; const int MAXN = 2e2 + ;
const int MAX = 6e3;
struct node{
int x, y;
}gel[MAXN]; int dp[MAXN][MAX]; int main(void){
ll x;
int n, k, cnt = ;
cin >> n >> k;
for(int i = ; i <= n; i++){
cin >> x;
while(x % == ){
gel[i].x += ;
x /= ;
}
while(x % == ){
gel[i].y += ;
x /= ;
cnt++;
}
}
memset(dp, -, sizeof(dp));
dp[][] = ;
for(int i = ; i <= n; i++){
for(int j = k; j >= ; j--){
for(int l = gel[i].y; l <= cnt; l++){
if(dp[j - ][l - gel[i].y] != -) dp[j][l] = max(dp[j][l], dp[j - ][l - gel[i].y] + gel[i].x);
}
}
}
int sol = ;
for(int i = ; i <= MAX; i++){
sol = max(sol, min(i, dp[k][i]));
}
cout << sol << endl;
return ;
}
最新文章
- Elasticsearch5.1.1+ik分词器+HEAD插件安装小记
- 2016HUAS_ACM暑假集训4A - 递推
- 张恭庆编《泛函分析讲义》第二章第2节 $Riesz$ 定理及其应用习题解答
- Infobright高性能数据仓库
- cognos8.3 sample在DB2里的安装
- yii2 AR需要注意的地方
- Android ART简介
- Hadoop学习笔记-008-CentOS_6.5_64_yum安装mysql
- hibernate的对象状态分析
- RecyclerView 配合 DiffUtil,好用到飞起
- servlet入门学习之Web容器
- iTOP-4412开发板-串口转接小板的使用文档
- Oracle使用笔记(三)
- window.onload和document.ready
- Spring Boot 项目实战(一)Maven 多模块项目搭建
- Python赋值与深浅拷贝
- PHP数组排序函数有哪些
- LaTeX技巧10:LaTeX数学公式输入初级入门
- Oracle体系结构之OFM管理
- Binary Tree Inorder Traversal leetcode java