CF837D Round Subset

洛谷评测传送门

题目描述

Let's call the roundness of the number the number of zeros to which it ends.

You have an array of nn numbers. You need to choose a subset of exactly kk numbers so that the roundness of the product of the selected numbers will be maximum possible.

输入格式

The first line contains two integer numbers nn and kk ( 1<=n<=200,1<=k<=n1<=n<=200,1<=k<=n ).

The second line contains nn space-separated integer numbers a_{1},a_{2},...,a_{n}a1,a2,...,a**n ( 1<=a_{i}<=10^{18}1<=a**i<=1018 ).

输出格式

Print maximal roundness of product of the chosen subset of length kk .

题意翻译

题目描述

我们把一个数的 roundness 值定义为它末尾 00 的个数。

给你一个长度为 nn 的数列,要求你从中选出 kk 个数,使得这些选出的数的积的 roundness 值最大。

输入格式

第一行包括两个正整数 nn 和 kk(1 \leq n \leq 2001≤n≤200,1 \leq k \leq n1≤kn)。

第二行包括 nn 个空白分隔的数 a_1,a_2,\ldots,a_na1,a2,…,a**n(1 \leq a_i \leq 10^{18}1≤a**i≤1018)。

输出格式

输出一个整数,是选择 kk 个数并作积的最大 roundness 值。

样例解释

在第一个例子中,有三种选法。[50,4][50,4] 的积是 200200,roundness 值是 22;[4,20][4,20] 的积是 8080,roundness 值是 11;[50,20][50,20] 的积是 10001000,roundness 值是 33。

第二个例子中选法 [15,16,25][15,16,25] 的积是 60006000,roundness 值是 33。

第三个例子中所有的选法的积的 roundness 值都是 00。

translated by @poorpool

输入输出样例

输入 #1复制

输出 #1复制

输入 #2复制

输出 #2复制

输入 #3复制

输出 #3复制

说明/提示

In the first example there are 3 subsets of 2 numbers. [50,4][50,4] has product 200 with roundness 2, [4,20][4,20] — product 80, roundness 1, [50,20][50,20] — product 1000, roundness 3.

In the second example subset [15,16,25][15,16,25] has product 6000, roundness 3.

In the third example all subsets has product with roundness 0.

题解:

2019.10.29模拟赛T1原90分场

思路假了被出题人@ysy20021208把数据卡成了70.感谢出题人(笔芯.jpg)

一开始的思路是把原数拆分成2和5,然后设置\(dp[i][j]\)表示前\(i\)个数中选择\(j\)个数的最大的\(roundness\)值,状态转移就是:

\[dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+cnt5[i]); \]

\(cnt5[]\)为5的数量)

我犯了一个想当然的错误:质因数分解后一定\(5\)的数量会更少一些。当然,如果把\(2,5\)的数量取\(min\),这个思路也是不对的,连样例都过不去。

后来重新捋思路:发现这道题的一个症结所在就是协调质因子中2和5的关系使得选取的数对后导零有最大的贡献。这个贡献不仅跟某一个数质因子中2,5的数量有关,还跟这个数列中我们选取了什么数有关。

那么这道题就变成了一个这样的背包问题:

我们设置\(dp[i][j]\)表示选取\(i\)个数、5有\(j\)个的最大2的个数。

那么会有这样的一个转移方程:

\[dp[i][j]=max(dp[i][j],dp[i-1][j-cnt5[i]]+cnt2[i]); \]

当然,这个数组只是处理出一个最优矩阵。我们最终出解的时候还要进行统计答案。

具体操作详见代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
int n,m,ans,tmp;
int a[210],cnt2[210],cnt5[210];
int dp[210][20000];
//设dp[i][j]表示选i个物品,5有j个时2的最多数量。
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        tmp=a[i];
        while(tmp%2==0)
            cnt2[i]++,tmp/=2;
        while(tmp%5==0)
            cnt5[i]++,tmp/=5;
    }
    memset(dp,-1,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
            for(int k=10000;k>=cnt5[i];k--)
                dp[j][k]=max(dp[j][k],dp[j-1][k-cnt5[i]]+cnt2[i]);
    for(int i=0;i<=10000;i++)
        ans=max(ans,min(i,dp[m][i]));
    printf("%lld",ans);
    return 0;   
}