首页 > 代码库 > Codeforces 837D Round Subset - 动态规划 - 数论

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 - 动态规划 - 数论