zoukankan      html  css  js  c++  java
  • 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
    ", res);
    44     return 0;
    45 }
  • 相关阅读:
    HDU 2116 Has the sum exceeded
    HDU 1233 还是畅通工程
    HDU 1234 开门人和关门人
    HDU 1283 最简单的计算机
    HDU 2552 三足鼎立
    HDU 1202 The calculation of GPA
    HDU 1248 寒冰王座
    HDU 1863 畅通工程
    HDU 1879 继续畅通工程
    颜色对话框CColorDialog,字体对话框CFontDialog使用实例
  • 原文地址:https://www.cnblogs.com/MasterSpark/p/7446005.html
Copyright © 2011-2022 走看看