CF837D Round Subset dp

题目描述
我们把一个数的 roundness 值定义为它末尾 0 0 0 的个数。
给你一个长度为 n n n 的数列,要求你从中选出 k k k 个数,使得这些选出的数的积的 roundness 值最大。
n ≤ 200 , k ≤ n , a i ≤ 1 0 18 n≤200,k≤n,a_i≤10^{18} n200knai1018

分析:
显然考虑每个数 2 2 2的质因数与 5 5 5质因数个数。我们可以设 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示前 i i i个数,选了 j j j个数, 5 5 5因子个数为 k k k时, 2 2 2因子的最大个数。转移显然。第一维可以压掉, k k k的大小不会很大, 6000 6000 6000就可以了。(大了时间也不够)

代码:

#include 
#include 
#include 
#define LL long long

const int maxn=201;

using namespace std;

int n,m,ans;
int a[maxn],b[maxn],sum[maxn],f[maxn][maxn*30];
LL x;

int main()
{
     
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
     
		scanf("%lld",&x);
		while (x%2==0)
		{
     
			a[i]++;
			x/=2;
		}
		while (x%5==0)
		{
     
			b[i]++;
			x/=5;
		}
		sum[i]=sum[i-1]+b[i];
	}
	for (int j=0;j<=m;j++)
	{
     
		for (int k=0;k<=sum[n];k++) f[j][k]=-0x3f3f3f3f;
	}
	f[0][0]=0;
	for (int i=1;i<=n;i++)
	{
     
		for (int j=m;j>0;j--)
		{
     
			for (int k=sum[i];k>=b[i];k--)
			{
     
				f[j][k]=max(f[j-1][k-b[i]]+a[i],f[j][k]);
			}
		}
	}		
	for (int k=1;k<=sum[n];k++) ans=max(ans,min(f[m][k],k));
	printf("%d",ans);
}

你可能感兴趣的:(DP)