Codeforces 837D Round Subset - 动态规划 - 数论

Posted 阿波罗2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 837D Round Subset - 动态规划 - 数论相关的知识,希望对你有一定的参考价值。

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

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

Input

The first line contains two integer numbers n and k (1 ≤ n ≤ 200, 1 ≤ k ≤ n).

The second line contains n space-separated integer numbers a1, a2, ..., an (1 ≤ ai ≤ 1018).

Output

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

Examples
Input
3 2
50 4 20
Output
3
Input
5 3
15 16 3 25 9
Output
3
Input
3 3
9 77 13
Output
0
Note

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

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

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


  题目大意 给定一个数组,从中选出k个数(不能选同一个数),使得这k个数的乘积的末尾的零的个数最多。

  根据小学的数学知识,我们知道一个数的末尾有多个零取决于它质因数分解后2的指数和5的指数的最小值。(10 = 2 × 5)

  所以我们初步得到动态规划的状态f[i][j][k]表示,从前i个数中,选出j个数,使得它们的乘积质因数分解后2的指数为k,5的指数最大为多少。

  显然它有两种转移:选第i + 1个数,不选第i + 1个数。所以转移是显然的。

  然后您会得到MLE,所以加上黑科技bfs版 + 滚动数组动态规划,不知道能不能卡过,但是有一种很简单的优化方法。

  显然将题目中输入的一个数质因数分解后5的指数不会超过技术分享。所以我们可以把5个个数作为状态,2的个数作为状态的值,这样总状态数不会超过2003 * 25(刚刚是乘64)

  所以继续黑科技优化内存和时间就过了。

Code

  1 /**
  2  * Codeforces
  3  * Problem#837D
  4  * Accepted
  5  * Time: 187ms
  6  * Memory: 10604k
  7  */
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 typedef bool boolean;
 11 #define smax(a, b) a = max(a, b);
 12 template<typename T>
 13 inline boolean readInteger(T& u){
 14     char x;
 15     int aFlag = 1;
 16     while(!isdigit((x = getchar())) && x != - && x != -1);
 17     if(x == -1) {
 18         ungetc(x, stdin);    
 19         return false;
 20     }
 21     if(x == -){
 22         x = getchar();
 23         aFlag = -1;
 24     }
 25     for(u = x - 0; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - 0);
 26     ungetc(x, stdin);
 27     u *= aFlag;
 28     return true;
 29 }
 30 
 31 typedef class Status {
 32     public:
 33         int stage;
 34         int seced;
 35         int c5;
 36 }Status;
 37 
 38 int n, k;
 39 int *c2s, *c5s;
 40 int res = 0;
 41 
 42 inline void init() {
 43     long long x;
 44     readInteger(n);
 45     readInteger(k);
 46     c2s = new int[(n + 1)];
 47     c5s = new int[(n + 1)];
 48     for(int i = 1; i <= n; i++) {
 49         c2s[i] = c5s[i] = 0;
 50         readInteger(x);
 51         while(!(x & 1))    x >>= 1, c2s[i]++;
 52         while(!(x % 5))    x /= 5, c5s[i]++;
 53     }
 54 }
 55 
 56 queue<Status> que;
 57 int f[2][201][4001];
 58 inline void dp() {
 59     int last = 0;
 60     Status sta = (Status) {0, 0, 0};
 61     que.push(sta);
 62     memset(f, -1, sizeof(f));
 63     f[0][0][0] = 0;
 64     while(!que.empty()) {
 65         Status e = que.front();
 66         que.pop();
 67         
 68         int lastf = f[e.stage & 1][e.seced][e.c5];
 69         Status eu = e;
 70         eu.stage++;
 71         if(eu.stage != last) {
 72             last = eu.stage;
 73             memset(f[eu.stage & 1], -1, sizeof(f[0]));
 74         }
 75         
 76         if(f[eu.stage & 1][eu.seced][eu.c5] == -1 && eu.stage < n && eu.seced <= k)
 77             que.push(eu);
 78         else if(eu.stage == n && eu.seced == k)
 79             smax(res, min(eu.c5, lastf));
 80         smax(f[eu.stage & 1][eu.seced][eu.c5], lastf);
 81         
 82         eu.seced++, eu.c5 += c5s[eu.stage];
 83         if(f[eu.stage & 1][eu.seced][eu.c5] == -1 && eu.stage < n && eu.seced <= k)
 84             que.push(eu);
 85         else if(eu.stage == n && eu.seced == k)
 86             smax(res, min(eu.c5, lastf + c2s[eu.stage]));
 87         smax(f[eu.stage & 1][eu.seced][eu.c5], lastf + c2s[eu.stage]);
 88     }
 89 }
 90 
 91 inline void solve() {
 92     printf("%d\n", res);
 93 }
 94 
 95 int main() {
 96     init();
 97     dp();
 98     solve();
 99     return 0;
100 }

 

以上是关于Codeforces 837D Round Subset - 动态规划 - 数论的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 837D - Round Subset DP

[CF837D] Round Subset(滚动数组,01背包)

cf837d Round Subset

Codeforces Global Round 19

Codeforces Educational Codeforces Round 67

Codeforces Round 1132Educational Round 61