Codeforces 837D--Round Subset (DP)

原题链接:http://codeforces.com/contest/837/problem/D

 

题意:在n个数字中,取k个数,使这些数的乘积后缀“0”的个数最大,输出后缀0的最大数量。

 

思路:显然只有含有因子2和5的数相乘才能得到10的倍数,所以对每个数求因子2和5的个数。

这里运用背包的思想,对于 i 个数,假设总共有 j 个2因子数目,能够得到的5的因子数目最大为dp[i][[j],状态转移方程为:

dp[i][j]=max(dp[i][j], dp[i-1][dp[j-num_two]+num_five])

其中num_two和num_five是枚举到的某个数所含2和5的因子数。

最后求出min(i, dp[i][j])的最大值即可。

 

AC代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<vector>
 5 using namespace std;
 6 const int MAXN=205;
 7 const int INF=10000000;
 8 int dp[MAXN][MAXN*61];
 9 int main()
10 {
11     int n,k;
12     long long a;
13     scanf("%d %d", &n, &k);
14     int sum2=0;
15     for(int i=0;i<MAXN;i++){
16         for(int j=0;j<MAXN*61;j++)
17             dp[i][j]=-INF; 
18     } 
19     dp[0][0]=0;
20     for(int s=1;s<=n;s++){
21         scanf("%I64d", &a);
22         int x=0,y=0;
23         while(a%2==0){
24             a/=2;
25             x++;
26         }
27         while(a%5==0){
28             a/=5;
29             y++;
30         }
31         sum2+=x;
32         for(int i=min(s, k);i>=1;i--){//避免重复计算导致答案错误,从大到小 
33             for(int j=x;j<=sum2;j++){
34                 dp[i][j]=max(dp[i-1][j-x]+y, dp[i][j]);
35             }
36         }
37     }
38     int res=0,tmp;
39     for(int j=0;j<=sum2;j++){
40         tmp=min(j, dp[k][j]);
41         res=max(tmp, res);
42     }
43     printf("%d\n", res);
44     return 0;
45 }

 

posted @ 2017-08-28 22:00  Bangbangbanana  阅读(166)  评论(0编辑  收藏  举报