数论+dp Codeforces Beta Round #2 B
http://codeforces.com/contest/2/problem/B
题目大意:给你一个n*n的矩形,问从(1,1)出发到(n,n),把图中经过的所有的数字都乘在一起,最后这个数字有多少个0?
思路:经过分析,只有2和5出现的时候才会有0.所以我们预处理把这个数包含的所有的2和5都给拿出来就好了。但是我发现如果每次转移都要统计2和5的个数的话,状态就炸了,所以我只想到了这里TAT。后来看了一下题解以后发现,只需要知道目前到这个位置以后最小的2(或5)的个数就好了。
然后转移我也想了好半天。。。于是还是看了。。。2333(我好菜啊)
转移就是只需要知道最后最小的个数是2还是5,然后再通过该数字去转移就好了
于是早上+中午+下午3个小时就过去了= =
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = + ;
const LL inf = 1e17;
LL a[maxn][maxn];
pair<LL, LL> p[maxn][maxn];
LL dp[maxn][maxn][];
int n;
/*
定义dp[i][j]表示到(i,j)所经过的0的最少的个数
0只在2*5的时候出现,所以只需要统计2和5的个数即可
以上思路是行不通的,因为这样子的话dfs或者dp都会有两个变量,所以会超级难写(TAT我写了一个早上)
所以我们要找一下两者当中的共同点。我们只需要找目前状态的2或5的最大值就好了
*/
pair<LL, LL> cal(LL val){
pair<LL, LL> cnt = mk(, );
LL tmp = val;
while (val % == && val) {cnt.fi++; val /= ;}
val = tmp;
while (val % == && val) {cnt.se++; val /= ;}
return cnt;
}
vector<char> v; bool dfs(int x, int y, int k){///0 is first, 1 is second
//printf("x = %d y = %d\n", x, y);
if (x > n || y > n || x < || y < ) return false;
if (x == && y == ) return true;
if (dp[x - ][y][k] < dp[x][y - ][k]){
if (dfs(x - , y, k)) {v.push_back('D'); return true;}
}
else {
if (dfs(x, y - , k)) {v.push_back('R'); return true;}
}
return false;
} int main(){
cin >> n;
memset(p, -, sizeof(p));
bool flag = false;
pair<int, int> zero;
for (int i = ; i <= n; i++){
for (int j = ; j <= n; j++){
scanf("%lld", &a[i][j]);
p[i][j] = cal(a[i][j] == ? : a[i][j]);///当做10,先消去0的影响
if (a[i][j] == ) {flag = true; zero = mk(i, j);}
}
}
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++){
for (int k = ; k < ; k++)
dp[i][j][k] = inf;
if (p[i][j].fi == -) p[i][j] = mk(inf, inf);
}
dp[][][] = p[][].fi, dp[][][] = p[][].se;
for (int i = ; i <= n; i++){
for (int j = ; j <= n; j++){
if (i == && j == ) continue;
dp[i][j][] = min(dp[i - ][j][], dp[i][j - ][]) + p[i][j].fi;
dp[i][j][] = min(dp[i - ][j][], dp[i][j - ][]) + p[i][j].se;
}
}
/*
haha;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
printf("%lld%c", min(dp[i][j][0], dp[i][j][1]), j == n ? '\n' : ' ');
*/
LL ans = min(dp[n][n][], dp[n][n][]);
if (flag && ans >= flag){
ans = 1LL * flag;
printf("%lld\n", ans);
int cnt = ;
for (int i = ; i <= zero.fi; i++) printf("D"), cnt++;
for (int i = ; i < n; i++) printf("R"), cnt++;
for (int i = zero.fi + ; i<= n; i++) printf("D"), cnt++;
cout << endl;
return ;
}
printf("%lld\n", ans);
dfs(n, n, dp[n][n][] > dp[n][n][]);
for (int i = ; i < v.size(); i++)
printf("%c", v[i]);
cout << endl;
return ;
} /*
4
1 10 10 10
1 0 1 10
10 10 2 10
1 10 1 1
*/
数论+dp Codeforces Beta Round #2 B的更多相关文章
- 暴力/DP Codeforces Beta Round #22 (Div. 2 Only) B. Bargaining Table
题目传送门 /* 题意:求最大矩形(全0)的面积 暴力/dp:每对一个0查看它左下的最大矩形面积,更新ans 注意:是字符串,没用空格,好事多磨,WA了多少次才发现:( 详细解释:http://www ...
- 状压dp Codeforces Beta Round #8 C
http://codeforces.com/contest/8/problem/C 题目大意:给你一个坐标系,给你一个人的目前的坐标(该坐标也是垃圾桶的坐标),再给你n个垃圾的坐标,这个人要捡完所有的 ...
- Codeforces Beta Round #17 D. Notepad (数论 + 广义欧拉定理降幂)
Codeforces Beta Round #17 题目链接:点击我打开题目链接 大概题意: 给你 \(b\),\(n\),\(c\). 让你求:\((b)^{n-1}*(b-1)\%c\). \(2 ...
- Codeforces Beta Round #16 E. Fish (状压dp)(概率dp)
Codeforces Beta Round #16 (Div. 2 Only) E. Fish 题目链接:## 点击打开链接 题意: 有 \(n\) 条鱼,每两条鱼相遇都会有其中一只吃掉对方,现在给你 ...
- Codeforces Beta Round #13 C. Sequence (DP)
题目大意 给一个数列,长度不超过 5000,每次可以将其中的一个数加 1 或者减 1,问,最少需要多少次操作,才能使得这个数列单调不降 数列中每个数为 -109-109 中的一个数 做法分析 先这样考 ...
- Codeforces Beta Round #62 题解【ABCD】
Codeforces Beta Round #62 A Irrational problem 题意 f(x) = x mod p1 mod p2 mod p3 mod p4 问你[a,b]中有多少个数 ...
- Codeforces Beta Round #83 (Div. 1 Only)题解【ABCD】
Codeforces Beta Round #83 (Div. 1 Only) A. Dorm Water Supply 题意 给你一个n点m边的图,保证每个点的入度和出度最多为1 如果这个点入度为0 ...
- Codeforces Beta Round #77 (Div. 2 Only)
Codeforces Beta Round #77 (Div. 2 Only) http://codeforces.com/contest/96 A #include<bits/stdc++.h ...
- Codeforces Beta Round #67 (Div. 2)
Codeforces Beta Round #67 (Div. 2) http://codeforces.com/contest/75 A #include<bits/stdc++.h> ...
随机推荐
- 移动app的一些心得
周末的时候闲着没事,看到了个开源的红旅动漫的APP,于是自己就拿下来写了下,整个网站作者也解析成了接口,所以就可以写成app了,作者写的是用mui开发的,可以通过hbuilder软件打开,进行查看源代 ...
- JS实现点击弹出对应的索引
如果这样写的话 ,弹出来一直是2,原因 这个i ,循环已经结束,i 的值已经是2了,所以需要再前面添加: items[i].index=i; //添加一个属性 ,技术一下 这个索引值 aler ...
- 2016 C++及系统软件技术大会亮点
2016 C++及系统软件技术大会将于201610月28日-29日在上海举办!此次2016 C++及系统软件技术大会秉承"全球专家. 连接智慧"的理念!大会特邀C++之父Bjarn ...
- php 基础篇 php 进阶篇
1:echo 12*3: 2 echo "Welcome" . " to imooc!";字符串连接. 3>foreach($shuzu as $key ...
- hdu_5963_朋友(找规律)
题目链接:hdu_5963_朋友 题意: 中文,不解释 题解: 把样例拿出来看看,你会发现以x为节点是否能赢,就是与x相连的边权值的和或者异或是否为奇数. #include<bits/stdc+ ...
- 经典dp 最长公共子序列
首先,说明一下子序列的定义…… 一个序列A={a1,a2,a3,...,an},从中删除任意若干项,剩余的序列叫A的一个子序列. 很明显(并不明显……),子序列……并不需要元素是连续的……(一开始的时 ...
- tomcat的事件监听
//事件涉及的三个组件:事件源.事件对象.事件监听器 //一个总的事件监听器接口,所有不同分类的事件监听器都继承这个接口 public interface EventListener {} //例如 ...
- Spring的Resource
通过Spring Resource接口获取资源(取自http://haohaoxuexi.iteye.com/blog/2016305)目录1 Resource简介2 通过ResourceLoader ...
- robotframework代码定位感悟
robotframework代码定位感悟: 在做自动化的时候,有时候还是要考虑真实的操作,考虑人为反应,网络,页面渲染,服务器处理请求的过程及数据是否真实到达响应的位置, 不能一味的按照程序的速度 去 ...
- Jenkins - 持续集成环境搭建【转】
1. Jenkins 概述 Jenkins是一个开源的持续集成工具.持续集成主要功能是进行自动化的构建.自动化构建包括自动编译.发布和测试,从而尽快地发现集成错误,让团队能够更快的开发内聚的软件. 2 ...