1. 程式人生 > 實用技巧 >b_vj_末尾有最多0的乘積(類揹包)

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));
    cout<<mx; 
    return 0;
}