传送门:点击打开链接
Let's call the roundness of the number the number of zeros to which it ends.
You have an array of n numbers. You need to choose a subset of exactly k numbers so that the roundness of the product of the selected numbers will be maximum possible.
The first line contains two integer numbers n and k (1 ≤ n ≤ 200, 1 ≤ k ≤ n).
The second line contains n space-separated integer numbers a1, a2, ..., an (1 ≤ ai ≤ 1018).
Print maximal roundness of product of the chosen subset of length k.
3 2 50 4 20
3
5 3 15 16 3 25 9
3
3 3 9 77 13
0
In the first example there are 3 subsets of 2 numbers. [50, 4] has product 200 with roundness 2, [4, 20] — product 80, roundness 1,[50, 20] — product 1000, roundness 3.
In the second example subset [15, 16, 25] has product 6000, roundness 3.
In the third example all subsets has product with roundness 0.
题意是给定n个数,从中选取k个数,问这k个数相等得到的数中,最多有几个0.
都结束了才做的题,发现标签是DP,不然怎么也想不到是DP。离散中学到0是由2和5相乘得到的。然后二维DP,(i,j)表示第i个数取前j个最大的可能,推不出递推式,一狠心设了个4维DP,后两位表示2和5的个数,又觉得i,j没用了。想了好久,觉得用i表示前n个数,j表示前i个数中所有质因子为2的和,dp[i][j]表示当前状态下所有质因子为5的个数的和。这样只需要数组的第二维开的稍大些,就可以解决。然后可以得到递推式:dp[i][j]=max(dp[i][j],dp[i-1][j-ans2]+ans5);最后确定了k的个数,扫描j,j从i到数组结束,注意要取2和5个数小的那一个,所以是min(i,dp[k][i])。注意long long的使用,防止爆数据。
代码实现:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=205;
ll dp[maxn][60*maxn];
ll map[maxn],ans2;
ll judge(ll x)
{
ll ans1=0;
ll temp=x;
ans2=0;
while(temp)
{
if(x%2==0)
{
ans1++;
x/=2;
}
else
break;
}
while(temp)
{
if(x%5==0)
{
ans2++;
x/=5;
}
else
break;
}
return ans1;
}
int main()
{
ll n,k,i,j,x,ans1,l;
while(cin>>n>>k)
{
memset(dp,-0x3f3f3f3f,sizeof(dp));
dp[0][0]=0;
for(i=0;i<n;i++)
{
cin>>x;
ans1=judge(x);
for(j=k;j>=1;j--)
{
for(l=ans1;l<60*maxn;l++)
{
dp[j][l]=max(dp[j][l],dp[j-1][l-ans1]+ans2);
}
}
}
ll ans=0;
for(i=1;i<60*maxn;i++)
{
ans=max(ans,min(i,dp[k][i]));
}
cout<<ans<<endl;
}
return 0;
}