习题:Round Subset(背包)
题目
思路
考虑如果末尾是0,那么一定是一个2和一个5组合起来
之后就是背包的板子了
这里有一个小优化,第二位考虑5的数量而不是2的数量
代码
#include<iostream>
#include<cstring>
using namespace std;
int dp[2][205][5155];//滚动,选了j个数,有k个5,最大能选出的2
int n,m,ans;
int cnt2[205],cnt5[205],limit;
int la,now;
void divide(long long val,int _ind)
{
if(val==0)
return;
while(val%2==0)
{
cnt2[_ind]++;
val/=2;
}
while(val%5==0)
{
cnt5[_ind]++;
val/=5;
}
limit+=cnt5[_ind];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
long long val;
cin>>val;
divide(val,i);
}
//for(int i=1;i<=n;i++)
// cout<<cnt2[i]<<' '<<cnt5[i]<<endl;
memset(dp,-1,sizeof(dp));
la=0,now=1;
dp[1][0][0]=0;
dp[0][0][0]=0;
for(int i=1;i<=n;i++)
{
la=now;
now^=1;
for(int j=1;j<=min(i,m);j++)
{
for(int k=0;k<=limit;k++)
{
dp[now][j][k]=dp[la][j][k];
if(k<cnt5[i])
continue;
if(dp[la][j-1][k-cnt5[i]]!=-1)
{
dp[now][j][k]=max(dp[la][j][k],dp[la][j-1][k-cnt5[i]]+cnt2[i]);
if(j==m)
ans=max(ans,min(dp[now][j][k],k));
}
}
}
}
cout<<ans;
return 0;
}
/*
3 1
1000000000000000000 800000000000000000 625
*/

浙公网安备 33010602011771号