首页 > 其他分享 >CF1570D 题解

CF1570D 题解

时间:2023-09-09 19:57:33浏览次数:45  
标签:10 set 数组 映射 CF1570D 题解 哈希 unordered

思路分析

前言

题解区好似没有用哈希的啊。

发现大家都在用 map 来存是否出现过数字,但是需要注意的是,map 的单次查询时间复杂度是 \(\mathcal O(\log n)\) 的,对于大规模的数据就很可能会 TLE。所以,我们可以使用哈希的方法来判断数字是否出现过。

浅谈哈希

哈希,是通过哈希函数将数据映射到数组的某个位置上的技术。如果哈希函数实现的好,那么不同的数据几乎不会映射到同一个上。如果发现了相同,那么就需要采取一些方法来规避了。

这里介绍一下拉链法,思路很简单,就是对于不同的数据映射到了一个相同位置的情况下,那么就开一个 vector 来存储所有映射到了这里的值。查找时遍历整个 vector 就可以进行查值了。

做法分析

首先,我们可以无限枚举 \(x+1\) 并且去除末尾的 \(0\) 后会出现的数字。但是这样我们是一定会陷入无限循环的。为什么呢?不仅仅是因为我们没有强制退出循环,更深层的原因是因为我们形成了一个环。容易证明,我们这样枚举是一定可以回到之前访问过的一个数字的。

如何处理这个情况呢?

  • 数组?但是 \(x\) 的上界达到了 \(10^9\),如果开一个元素数量为 \(10^9\) 的数组来存储,那么我们需要大约 \(7\text{ GiB}\) 的空间,铁定 MLE。

  • 我们可以定义一个 unordered_set<int> 来存储之前到达过的值。unordered_set<int> 是 STL 中的一个容器。它的底层是使用哈希实现的,理论时间复杂度是 \(\mathcal O(1)\) 的,但是常数比较大,对于时间限制比较紧张的题目建议手写哈希(当然数组开的下尽量用数组来存储),也不难写。当我们发现这次的数字已经出现过时,那么就可以断定接下来不会找到新的数值了,直接输出 unordered_set<int> 的大小即可。

代码实现

#include <iostream>
#include <unordered_set>
// 如果要使用 unordered_set,那么就必须调用这个库。
int main() {
		int x;
		std::unordered_set<int> h; 
		std::cin >> x;
		h.insert(x); // 开始需要插入开始值
		while (true) {
			++x;
			while (!(x % 10)) x /= 10;
			if (h.find(x) != h.end()) { // 判断数字是否已经出现过了
				std::cout << h.size(); // 输出 h 的大小
				return 0;
			}
			h.insert(x);
		}
		return 0;
}

标签:10,set,数组,映射,CF1570D,题解,哈希,unordered
From: https://www.cnblogs.com/IShallReturn/p/17690052.html

相关文章

  • 【题解】Educational Codeforces Round 143(CF1795)
    A.TwoTowers题目描述:有\(a,b\)两座由红蓝色方块垒成的塔,其中\(a\)的高度为\(n\);\(b\)的高度为\(m\),用R代表红色;用B代表蓝色。你可以多次把其中一座顶端的方块移到另一座的顶端(可以不移动)。问有没有一种方法可以使两座塔中均没有连续的同颜色方块。题目分析:可以......
  • UVA202 题解
    思路分析前言又是一道小模拟题,不过细节巨多,可以用来锻炼自己的代码能力。解法本题实际上就是模拟长除法的计算过程,其中每一步除法时都有被除数及其余数,当被除数出现重复时就表示出现循环节了。所以需要记录每一次的被除数及其在循环小数中的位置,需要判断当除数不够除,每一次补......
  • 题解 [CQOI2009] 中位数
    题目链接要想使得数字\(x\)是中位数,就必须选出\(k\)个小于\(x\)的数和\(k\)个大于\(x\)的数。我们考虑对数字附上特殊值,小于\(x\)的数赋值为\(-1\),大于\(x\)的数赋值为\(1\),\(x\)则赋值为\(0\),那么若一段包含\(x\)的连续序列的和等于\(0\),就可以说明这段连......
  • [题解] Codeforces Round 895 (Div. 3) F~G
    CodeforcesRound895(Div.3)F~GF.SellingaMenageri考虑如何让卖出的价格翻倍,那么自然是从\(i\toa_i\)。通过这样连边,我们可以发现,边集构成了基环树森林。显而易见的是,如果不考虑环,那么图就是拓扑图,按照拓扑关系跑一遍,就可以使得所有点价值最多。现在考虑环上的问题......
  • [AGC036C] GP 2 题解
    洛谷题目链接AT原题考虑构造出来的序列\(a\)的特征,因为每次会给\(a_i\)加\(1\),\(a_j\)加\(2\),所以每次操作后\(\suma_i\)会加上\(3\)。所以有\(\suma_i=3m\)。又因为每次操作只给一个数加\(1\),所以每次操作要么给序列加入一个奇数,要么使原来的一个奇数变成偶数......
  • [题解] CF29D Ant on the Tree
    CF29DAntontheTree题目知识点:LCA。题目传送门题意给定一棵以\(1\)为节点的树,再给定树的所有叶子节点的一个序列。现在执行一个操作:从\(1\)开始遍历每个节点,并返回根,要求每条边经过的次数一定为\(2\)。问是否能够使得访问节点序列中叶子节点的序列符合给定序列的条......
  • P2206题解
    题目大意:给定一些指令,计算需要多大的舞台。这是一道大模拟!!!只要遍历每次指令,然后判断是否摔倒,摔倒输出`-1`否则记录,最后求出面积就行了。最后附上代码1#include<bits/stdc++.h>2usingnamespacestd;3constintxx[]={-1,0,1,0},yy[]={0,1,0,-1};//不同......
  • CF1513C题解
    一道递推由于对于一个数x,可得x+10-x=10(废话)于是问题就变成了0+m次,然后x+m就变成0+x+m(还是废话)于是可以写一个递推。首先对于函数f(m)可分为m ≤9和m>9,然后可得出递推式结果为1或f(m-9)+f(m-10),所以我们可以直接求出结果再分解数位求值。最后贴上代码......
  • P2203题解
    题意给定一个环形01序列,每次变化时,对于每个位置,如果前一个值是1,则当前值翻转。求变化B次后的序列。思路由于B的值很大,所以如果对每一次变化进行模拟,效率非常低下。不难发现,每一次变化后的状态完全是由当前状态决定的,而N的范围很小,所以可能的状态总数2^N也不是很大......
  • CF812B题解
    康了康唯一的题解,说没必要用DP,我就给出DP的解法。这其实是道水题,唯一的坑是有可能楼上没有开的灯,坑了我们机房的一堆人(WAontest4),剩下的就是DP。我们用a[n][0],表示第n层的第一个房间,用a[n][1],表示第n层的最后一个房间。这里提供一个收集型的写法。所以可得状态转移......