您的位置:首页 > 其它

Codeforces 837 D Round Subset

2017-08-04 13:13 295 查看
题目地址

题意:给你个序列,选择k个数,求乘积的后缀零最多

思路:因为0是由2和5的乘积组成的,然后经别人提醒可以用dp去写,其实就可以转变为01背包的问题(注释比较详细)

PS:为什么用5来做0的标准,因为2比较容易找到(我是这样觉得的)

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#define N 210
#define M 13000
#define LL long long
#define inf 0x3f3f3f3f3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
#define getMid (l+r)>>1
#define movel ans<<1
#define mover ans<<1|1
using namespace std;
const LL mod = 1e9 + 7;
const double eps = 1e-9;
struct node {
int num5, num2;
}num
;
LL dp
[M];//dp[i][j],i代表的是第i个数字,j代表的是,dp记录的是能构成0的个数
int main(){
cin.sync_with_stdio(false);
LL n, k;
while (cin >> n >> kk){
for (int i = 0; i<n; i++){
LL nums;
cin >> nums;
num[i].num5 = 0, num[i].num2 = 0;
while (nums % 5 == 0) {
num[i].num5++, nums /= 5;
}
while (nums % 2 == 0) {
num[i].num2++, nums /= 2;
}
}
memset(dp, -inf, sizeof(dp));
dp[0][0] = 0;
for (int i = 0; i<n; i++){//当前选择的数字
for (int j = kk; j >= 1; j--){//选择放在第j个拿
for (int k = M - 1; k >= 0; k--){//当前2的个数
if (k - num[i].num2 >= 0)
dp[j][k] = max(dp[j][k], dp[j - 1][k - num[i].num2] + num[i].num5);
}
}
}
LL ans = 0;
for (LL i = 0; i<M; i++){
ans = max(ans, min(i, dp[kk][i]));

}
cout << ans << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: