CF_837D

传送门:https://codeforces.com/problemset/problem/837/D

这道题让我很惆怅......第一次打了个假贪心跑到的40多点,后面竟没破过30个点

通过这道题又让我提起了对动态规划的的三要素:状态,阶段,决策 的重视。

犯的错误有:

  1. 没有赋初值
  2. 没有判合法状态

这道题的解法:你会发现10只与最后所有选择数的2的次数和5的次数。

所以设状态 f[i][j]已经选了i个数,有j个素因数2最多拥有多少个5。

转移每次处理当前数的2的次数和5的次数,跑背包即可。(记得初值和合法判断)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
typedef long long ll;
#define R register
using namespace std;
ll n,m;
struct ddd{
    ll a,b,c;
}q[210];
void ch(int x){
    ll v=q[x].a;
    while(v%2==0) q[x].b++,v/=2;
    while(v%5==0) q[x].c++,v/=5;
    return;
}
ll sum,f[210][6009],ans;
int main (){
    scanf("%lld%lld",&n,&m);
    memset(f,-1,sizeof(f));
    for(R ll i=1;i<=n;i++) cin>>q[i].a,ch(i);
    f[0][0]=0;
    for(R ll i=1;i<=n;i++){
        sum+=q[i].b;
        for(R ll j=min(i,m);j>=1;j--){
            for(R ll k=sum;k>=q[i].b;k--){
                if(f[j-1][k-q[i].b]==-1) continue;
                f[j][k]=max(f[j][k],f[j-1][k-q[i].b]+q[i].c);
            }
        }
    }
    for(R ll i=0;i<=sum;i++) ans=max(ans,min(i,f[m][i]));
    printf("%lld",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/coclhy/p/11633598.html