b_vj_末尾有最多0的乘积(类背包)

给定N个正整数A1, A2, ... AN。从中选出M个整数,使得它们的乘积末尾有最多的0。

思路:f[i][j][k]表示从前i个数中选出j,且一共有k个因数5时,最多的2的个数

#include<iostream>
#include<cstring>
using namespace std;
const int N=105;
int n,m,nums[N],c5,a[N],b[N],f[N][N][1000]; //a[i]第i个数2的因子的个数
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n>>m; for (int i=1; i<=n; i++) cin>>nums[i];
    for (int i=1; i<=n; i++) {
        while (nums[i]%2==0 && nums[i]) a[i]++, nums[i]/=2;
        while (nums[i]%5==0 && nums[i]) b[i]++, nums[i]/=5, c5++;
    }
    memset(f,-1,sizeof f), f[0][0][0]=0;
    for (int i=1; i<=n; i++)
    for (int j=0, t=min(i,m); j<=t; j++)
    for (int k=0; k<=c5; k++) {
        f[i][j][k]=f[i-1][j][k];
        if (j && k>=b[i] && f[i-1][j-1][k-b[i]]!=-1) 
            f[i][j][k]=max(f[i][j][k], f[i-1][j-1][k-b[i]]+a[i]);
    }
    int mx=0;
    for (int k=1; k<=c5; k++) mx=max(mx, min(f[n][m][k], k)); //因子2和5的个数中取最少的一个
    cout<<mx; 
    return 0;
}
原文地址:https://www.cnblogs.com/wdt1/p/13968327.html