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;
}