首页 > 其他分享 >Nule 题解

Nule 题解

时间:2023-08-05 22:23:06浏览次数:48  
标签:prime min 题解 个数 Nule 权值 include dp

1.题意简述:

给定一个N行N列的非负整数方阵,从左上角(1,1)出发,只能向下或向右走,且不能到达值为0的方格,求出一条到达右下角的最佳路径,所谓最佳路径是指途径的数的乘积的末尾连续的0最少。

2.样例解释:

4
1 3 0 0
0 8 2 25
6 5 0 3
0 15 7 4
2

这个样例有多重走法,这里给出两个:

1. 1->3->8->2->25->3->4 最终结果为14400

2.1->3->8->5->15->7->4 最终结果为50400

3.思路:

还记不记得以前做过的一道题:给出 n,求 n! 末尾含0的个数。

当时我们的思路是对于 \(1\) 到 \(n\) 的每个数找出其含质因子 \(2\) 和 \(5\) 的个数, \(0\) 的个数就是其最小值。

那么本题我们可以采用同样的思路:开出两个二维数组 \(dp2[i][j]\) 和 \(dp5[i][j]\),用于存储当走到第 \(i\) 行第 \(j\) 列时路径上含 \(2\) 的个数和含 \(5\) 的个数。

再分别做一遍动态规划,求出终点最小含 \(2\) 的个数和最小含 \(5\) 的个数,最终最少含 \(0\) 的个数就是其最小值。

3.注意

注意题目中说不能经过权值为 \(0\) 的边,所以我们在算每个点的权值含 \(2\) 的 \(5\) 的个数时要特判一下,如果权值为 \(0\),那么将其含 \(2\) 和含 \(5\) 的个数为无穷大,这样在状态更新时,系统就不会选择含 \(2\) 和 \(5\) 较多的数。

然后再贴一下状态转移方程:

dp[i][j] = min (dp[i][j], min (dp[i - 1][j], dp[i][j - 1])) + prime (a[i][j]);

这里的 \(prime\) 函数指分别判断每个数含 \(2\) 和 \(5\) 的个数。

4.代码

#include <iostream>
#include <algorithm>
#include <cstring>
//define int long long

using namespace std;

#define N 1010
#define For(i,j,k) for(int i=j;i<=k;i++)
#define IOS ios::sync_with_stdio(),cin.tie(),cout.tie()

int n, a[N][N], dp[N][N];
//我这里只用了一个二维数组,分两次判断每个数含2和含5的个数。
int prime_2 (int x) {
	if (x == 0) return 0x3f3f3f3f;
	//特判权值为0的情况
	int ans = 0;
	while (x % 2 == 0) {
		x /= 2;
		ans ++;
	} //只要这个数还能被2整除,就将答案加1
	return ans;
}

int prime_5 (int x) {
	if (x == 0) return 0x3f3f3f3f;
	//特判权值为0的情况
	int ans = 0;
	while (x % 5 == 0) {
		x /= 5;
		ans ++;
	}//只要这个数还能被5整除,就将答案加1
	return ans;
}

int main () {
    IOS;
	cin >> n;
	For (i, 1, n) {
		For (j, 1, n) {
			cin >> a[i][j];
		}
	}
	//现将dp数组初始化为一个很大的数
	memset (dp, 0x3f, sizeof dp);
	dp[1][1] = 0; //将起点的值更新为0

	For (i, 1, n) {
		For (j, 1, n) {
			dp[i][j] = min (dp[i][j], min (dp[i - 1][j], dp[i][j - 1])) + prime_2 (a[i][j]);	
			//套用状态转移方程
		}
	}
	int ans = dp[n][n]; //将终点最小含2的个数存储在ans中
	memset (dp, 0x3f, sizeof dp);
	dp[1][1] = 0; //第二次dp,要重新赋初值

	For (i, 1, n) {
		For (j, 1, n) {
			dp[i][j] = min (dp[i][j], min (dp[i - 1][j], dp[i][j - 1])) + prime_5 (a[i][j]);	
		}
	}
	//输出终点最小含2的个数与最小含5的个数的最小值
	cout << min(dp[n][n], ans) << endl;
	return 0;
}

标签:prime,min,题解,个数,Nule,权值,include,dp
From: https://www.cnblogs.com/linbaicheng/p/17608751.html

相关文章

  • P4426 [HNOI/AHOI2018] 毒瘤 题解
    P4426[HNOI/AHOI2018]毒瘤题解非常好虚树题目,融合了容斥的内容。简化题意给定一张\(n\)个点、\(m\)条边的图,求图的独立集个数。其中\(n\leq10^5\),\(n-1\leqm\leqn+10\)。独立集:对于图\(G(U,E)\)的一个点集\(S\),\(\forall(u,v)\inE\),不存在\(u\inS\)且......
  • String Game 题解
    题目传送门一道二分题。\(|p|\le2\times10^6\),考虑\(O(n\logn)\)的算法,而又要输出最大值,不难想到二分答案。二分删除字母的数量,用一个数组将删掉的字母的下标存起来,然后判断删除字符后的\(t\)是否是\(p\)的子序列即可。Code#include<bits/stdc++.h>#definelllong......
  • Painting the Fence 题解
    题目传送门一道枚举题。我们可以直接枚举那\(2\)个去掉的粉刷匠。先统计一下每个栅栏会被多少个粉刷匠刷到,然后枚举第一个被去掉的粉刷匠,然后计算剩下的粉刷匠会将每个栅栏刷到多少次,我们只需要看只能被刷\(1\)次的栅栏就行了。接着处理一个前缀和数组,记录前\(i\)个栅栏......
  • Vanya and Brackets 题解
    题目传送门一道枚举题。枚举左括号和右括号的位置括号,为了答案最优,左括号只能在开头或者*的右边。右括号只能在末尾或者*的左边。每一次枚举都计算一下这个加了括号后表达式的值,最后取最大值即可。Code#include<bits/stdc++.h>#definelllonglong#defineINF1e9usi......
  • Permutations 题解
    题目传送门一道枚举题。数据范围非常小,考虑暴力枚举全排列。可以dfs两次,第一次求出能使\(f(p)\)取得的最大值。第二次求出第\(m\)个排列。注意一下,第二次dfs的时候需要按字典序枚举。Code#include<bits/stdc++.h>#definelllonglong#defineINF1e9usingname......
  • Prefixes and Suffixes 题解
    题目传送门一道字符串题。我们考虑还原字符串后再一个一个的判断。很显然,这个字符串是由一个长度为\(n-1\)的前缀和后缀组成的。因此我们可以找到这\(2\)个长度为\(n\)的字符串,然后枚举哪个是前缀,哪个是后缀。值得注意的是,当你判断一个字符串为前缀时,如果后面出现了同样......
  • Educational Codeforces Round 151 (Rated for Div. 2) 题解
    A.ForbiddenInteger显然,当\(x\not=1\)时,直接输出\(n\)个\(1\)即可否则,如果\(n\)为奇数,那就输出\(\lfloor\frac{n}{2}\rfloor-1\)个\(2\)和\(3\);如果\(n\)为偶数,那就输出\(\frac{n}{2}\)个\(2\)(要看一下\(k\)的大小)B.ComeTogether因为Bob和Carol都......
  • 恋爱入门教学题解
    已知长度为\(n\)的三个两个实数序列\(A,B,X\),定义\(n\)个定义域为\(\R\)的函数\(f_1,f_2,\cdots,f_n\)。其中:\[f_k(x)=\sum_{i=1}^k|a_i(x-x_i)+b_i|\]现在,对于每一个\(k=1,2,\cdots,n\),求\(f_k\)的最小值。可以证明,最小值一定存在。\(n\le......
  • FJOI 树的重心题解
    从零开始暴切省选题题意简述给定一个\(n\)个点的树,每个点的编号从\(1\)至\(n\),问这个树有多少不同的连通子树,和这个树有相同的重心。分析1求重心首先要明确重心的定义。题目中给出:删掉某点\(i\)后,若剩余\(k\)个连通分量,那么定义\(d(i)\)为这些连通分量中点的个数......
  • P4850 [IOI2009] Raisins 题解
    前言:IOI还出这样水的纯记忆化搜索题?还是T4?真令人难以置信。题意:题目传送门一个N×M的矩阵,对于任意一个子矩阵,只能横着或竖着分割,并且分割一次的价值为改子矩阵的元素之和,现要将该矩阵分割成1×1的方格,求最小的分割总价值之和。思路:看到这是个最优化的题,且数据范围很......