zoukankan      html  css  js  c++  java
  • 【Codeforces837D】Round Subset

    本题在洛谷上的链接:https://www.luogu.org/problem/show?pid=CF837D


    好坑!绝对有毒!

    我的CF账号还没有权限提交,各种未知错误,把代码改得和题解几乎一样才过,%lld和typedef都不支持吗???动规思想及细节处理当然也很坑。

    这道题思想很简单,为了求末尾0的个数,就是要求分别分解出2和5的个数最小值,可以设dp[i][j][a][b]表示从前i个数中选取j个数,乘积分解出a个2,b个5是否可行,用min(a,b)更新答案即可。

    但还可以再优化,设dp[i][j][l]表示从前i个数中选取j个数,乘积分解出l个5时,最多还可以分解出几个2,就可以用min(l,dp[i][j][l])去更新答案。

    对的,这其实就是个背包问题,讨论每个数取或不取。

    另外时间上每什么问题,但空间却会爆,所以还要用到滚动数组。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn = 2, maxk = 205, max5 = 6000;
     9 
    10 int dp[maxn][maxk][max5], sum2[maxk], sum5[maxk], ans;
    11 
    12 int main() {
    13     int n, k;
    14     scanf("%d%d", &n, &k);
    15     long long a;
    16     for (int i = 1; i <= n; ++i) {
    17         cin >> a;
    18         while (a % 2 == 0) ++sum2[i], a /= 2;
    19         while (a % 5 == 0) ++sum5[i], a /= 5;
    20     }
    21     memset(dp, -1, sizeof(dp));
    22     dp[0][0][0] = 0;
    23     for (int i = 1; i <= n; ++i)
    24         for (int j = 0; j <= i && j <= k; ++j)
    25             for (int l = 0; l < max5; ++l) {    
    26                 dp[i % 2][j][l] = dp[(i - 1) % 2][j][l];
    27                 if (j >= 1 && l >= sum5[i] && dp[(i - 1) % 2][j - 1][l - sum5[i]] != -1)
    28                     dp[i % 2][j][l] = max(dp[i % 2][j][l], dp[(i - 1) % 2][j - 1][l - sum5[i]] + sum2[i]);
    29             }
    30     for (int l = 0; l < max5; ++l)
    31         ans = max(ans, min(l, dp[n % 2][k][l]));
    32     printf("%d", ans);
    33     return 0;
    34 }
    AC代码
  • 相关阅读:
    NYOJ 734
    NYOJ 762
    NYOJ 743
    NYOJ 478
    NYOJ 451
    NYOJ 461
    NYOJ 485
    NYOJ 333
    平均互信息
    ASCII码
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9890830.html
Copyright © 2011-2022 走看看