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.
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).
Print maximal roundness of product of the chosen subset of length k.
3 2
50 4 20
3
5 3
15 16 3 25 9
3
3 3
9 77 13
0
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
/**
* Codeforces
* Problem#837D
* Accepted
* Time: 187ms
* Memory: 10604k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;
#define smax(a, b) a = max(a, b);
template<typename T>
inline boolean readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-' && x != -);
if(x == -) {
ungetc(x, stdin);
return false;
}
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
return true;
} typedef class Status {
public:
int stage;
int seced;
int c5;
}Status; int n, k;
int *c2s, *c5s;
int res = ; inline void init() {
long long x;
readInteger(n);
readInteger(k);
c2s = new int[(n + )];
c5s = new int[(n + )];
for(int i = ; i <= n; i++) {
c2s[i] = c5s[i] = ;
readInteger(x);
while(!(x & )) x >>= , c2s[i]++;
while(!(x % )) x /= , c5s[i]++;
}
} queue<Status> que;
int f[][][];
inline void dp() {
int last = ;
Status sta = (Status) {, , };
que.push(sta);
memset(f, -, sizeof(f));
f[][][] = ;
while(!que.empty()) {
Status e = que.front();
que.pop(); int lastf = f[e.stage & ][e.seced][e.c5];
Status eu = e;
eu.stage++;
if(eu.stage != last) {
last = eu.stage;
memset(f[eu.stage & ], -, sizeof(f[]));
} if(f[eu.stage & ][eu.seced][eu.c5] == - && eu.stage < n && eu.seced <= k)
que.push(eu);
else if(eu.stage == n && eu.seced == k)
smax(res, min(eu.c5, lastf));
smax(f[eu.stage & ][eu.seced][eu.c5], lastf); eu.seced++, eu.c5 += c5s[eu.stage];
if(f[eu.stage & ][eu.seced][eu.c5] == - && eu.stage < n && eu.seced <= k)
que.push(eu);
else if(eu.stage == n && eu.seced == k)
smax(res, min(eu.c5, lastf + c2s[eu.stage]));
smax(f[eu.stage & ][eu.seced][eu.c5], lastf + c2s[eu.stage]);
}
} inline void solve() {
printf("%d\n", res);
} int main() {
init();
dp();
solve();
return ;
}
Codeforces 837D Round Subset - 动态规划 - 数论的更多相关文章
- CodeForces 837D - Round Subset | Educational Codeforces Round 26
/* CodeForces 837D - Round Subset [ DP ] | Educational Codeforces Round 26 题意: 选k个数相乘让末尾0最多 分析: 第i个数 ...
- Codeforces 837D - Round Subset(dp)
837D - Round Subset 思路:dp.0是由2*5产生的. ①dp[i][j]表示选i个数,因子2的个数为j时因子5的个数. 状态转移方程:dp[i][j]=max(dp[i][j],d ...
- Codeforces 837D Round Subset(背包)
题目链接 Round Subset 题意 在n个数中选择k个数,求这k个数乘积末尾0个数的最大值. 首先我们预处理出每个数5的因子个数c[i]和2的因子个数d[i] 然后就可以背包了. 设f[i] ...
- Codeforces 837D - Round Subset DP
先算出每个数的pop1(twonum),pop(fivenum)然后DP ans[i][j]表示选i个数有j个2时最多有多少个5 转移方程是 ;j--) { ;w++) { ans[j][w]=max ...
- CF837D Round Subset 动态规划
开始的时候数据范围算错了~ 我以为整个序列 2 和 5 的个数都不超过 70 ~ 一个非常水的 dp code: #include <bits/stdc++.h> #define M 75 ...
- Educational Codeforces Round 26 [ D. Round Subset ] [ E. Vasya's Function ] [ F. Prefix Sums ]
PROBLEM D - Round Subset 题 OvO http://codeforces.com/contest/837/problem/D 837D 解 DP, dp[i][j]代表已经选择 ...
- Codeforces Global Round 1 - D. Jongmah(动态规划)
Problem Codeforces Global Round 1 - D. Jongmah Time Limit: 3000 mSec Problem Description Input Out ...
- Codeforces Beta Round #17 D. Notepad (数论 + 广义欧拉定理降幂)
Codeforces Beta Round #17 题目链接:点击我打开题目链接 大概题意: 给你 \(b\),\(n\),\(c\). 让你求:\((b)^{n-1}*(b-1)\%c\). \(2 ...
- Codeforces 837D 动态规划
Codeforces 837D 动态规划 传送门:https://codeforces.com/contest/837/problem/D 题意: 给你n个数,问你从这n个数中取出k个数,这k个数的乘 ...
随机推荐
- Windows服务器时间不同步问题
一台域内的服务器时间不停地被修改,我先向用户收集了一些信息 只有这一台出现此问题,其他服务器均为正常(补充一下,问题快解决完的时候用户告诉我一个重要的消息,就是时间被修改了一段时间后自动会被修改回去) ...
- 编写带有下列声明的例程:第一个例程是个驱动程序,它调用第二个例程并显示String str中的字符的所有排列。例如,str是"abc", 那么输出的串则是abc,acb,bac,bca,cab,cba,第二个例程使用递归。
全排列在笔试面试中很热门,因为它难度适中,既可以考察递归实现,又能进一步考察非递归的实现,便于区分出考生的水平.所以在百度和迅雷的校园招聘以及程序员和软件设计师的考试中都考到了,因此本文对全排列作下总 ...
- python爬虫-基础入门-python爬虫突破封锁
python爬虫-基础入门-python爬虫突破封锁 >> 相关概念 >> request概念:是从客户端向服务器发出请求,包括用户提交的信息及客户端的一些信息.客户端可通过H ...
- 加减plugin
plugin插件↓↓ ;(function (underfined) { "use strict" var _global; //插件函数 /* var plugin = { ad ...
- SqlServer表和EXCEL数据互相复制方法
一.SqlServer表数据复制到excel 1.新建查询,用sql语句把表数据读出来 2.然后,选择数据,右键,复制(也可以点击连同标题复制),复制到记事本中(不然会乱码) 3.然后再把记事本的内容 ...
- [10]Windows内核情景分析---中断处理
中断处理 每个cpu有一张中断表,简称IDT. IDT的整体布局:[异常->空白->5系->硬](推荐采用7字口诀的方式重点记忆) 异常:前20个表项存放着各个异常的描述符(IDT表 ...
- 压缩和解压缩(I)
ZipArchive 压缩方法 -(void)zipArchiveWithFiles { //创建解压缩对象 ZipArchive *zip = [[ZipArchive alloc]init]; / ...
- mybatis源码解析9---执行器Executor解析
从前面分析我们知道了sql的具体执行是通过调用SqlSession接口的对应的方法去执行的,而SqlSession最终都是通过调用了自己的Executor对象的query和update去执行的.本文就 ...
- Spark With Mongodb 实现方法及error code -5, 6, 13127解决方案
1.spark mongo 读取 val rdd = MongoSpark.builder().sparkSession(spark).pipeline(Seq(`match`(regex(" ...
- react 页面存在多 input 时
this.setState({ [e.target.name]:e.target.value }) let o = {} o[e.target.name] = e.target.value this. ...