您的位置:首页 > 其它

【20150801-20150808】趣题详解

2015-09-01 18:47 183 查看

前言

  这个博客已经快一年没有更新了……

  翻看之前的题解和总结记录,顿感记录的快乐——回顾之前的知识,找回以前的记忆,理清头绪,这正是备战比赛时需要做的事。而拥有博客这个平台,能轻松地应对这个任务。

  是时候继续更新了。把这快十天中做过的一些有趣的题目讲讲吧。

  

【20150801】山峰

  题目大意:给出一个矩阵数组 ( 1≤n,m≤5001 \leq n,m \leq 500 ) 和一个数 dd。点 (x,y)(x,y) 上的数字为 h,它被称为“d-山峰”当且仅当从这个点出发,在不经过上面的数小于等于 h-d 的格子的前提下无法到达数字比它更大的格子上。问“d-山峰”的个数。

  

  这道题咋看上去像搜索,其实不然。因为每个点能走到的格子都是连成一片的(显然),很容易想到可以先把当前点能走到的点全部标记为“可行”,如果与这个点连成一起的区域中最大的数超过了这个点上的数,这个点就不能计入答案。

  这样一来,问题变成了“如何将所有【数字超过某个数的格子】标记为可行”以及“询问连续一片可行点的数的最大值”。根据这个想法深入思考,不难发现:如果我们将所有的点按数字从大到小排序,那么在遍历排好序的点时,可行点的数量是不递减的

  这就启发我们使用并查集解决问题:遍历这些点的时候我们把所有“需要标成可行”的点打上标记,也即与周围可行的点并到一起,成为一个个可行点集。由于点是排好序的,每次要标记的点必然是连续的一片,此时可以用个变量 pp 标记上一次已经标记了前 pp 个点,这样便不需要重复标记可行点,使得每个点只需要标记一次。在合并点集的时候顺便维护点集的最大值,就可以 O(1)O(1) 判断当前点了。总的时间复杂度为 O(nm)O(nm)。

  

【20150802】恭介的法则

  题目大意:给定一个正整数 n ( 1≤n≤7000001\leq n \leq700000 ),当正整数对 (x,y)(x,y) 满足 1x+1y=1n!\frac{1}{x}+\frac{1}{y}=\frac{1}{n!} 时称其符合条件。问符合条件的正整数对的个数。

  

  拿到这道题目,感觉就是分析条件中的那个等式,从中找出符合条件的 xx 与 yy 的规律。可惜数学功底差,写到一半无论如何都写不下去了。

  其实方法很简单。显然有x+yxy=1n!\frac{x+y}{xy}=\frac{1}{n!}  那么可以得出:x+y=ax+y=a xy=n!⋅axy=n!\cdot a  如果令 y=a−xy=a-x,就有x(a−x)=n!⋅a ⟹ a=x2x−n!x(a-x)=n!\cdot a~~~\Longrightarrow~~~a=\frac{x^2}{x-n!}  显然 aa 一定为正整数,也就是说 x>n!x>n! 。如果再令 x=n!+kx=n!+k,就有a=(n!)2+2kn!+k2k=(n!)2k+2n!+ka=\frac{(n!)^2+2kn!+k^2}{k}=\frac{(n!)^2}{k}+2n!+k  此时如果 aa 要是整数,就意味着 kk 是 (n!)2(n!)^2 的因子。那么 (n!)2(n!)^2 的因子个数就是我们需要的答案了。

  答案很大,需要使用高精度压位,但是这仍不足以在时限内通过此题

  注意到在进行高精度乘法的时候,每次乘的都是一个较小的数,可以先用另一个变量存储目前乘过的数的积,等到这个积比较大时答案再把它累乘上去,同时重置这个变量。这种做法能有效节省进行高精度乘法的次数,显著降低时间复杂度。

  

【20150804】合并果子

  题目来源:NOIP2004TG

  题目大意:给出 n 个正整数 ( 1≤n≤300001\leq n \leq 30000 ),任意两个正整数可以合并成一个正整数,合并后的数值以及代价皆为两数之和。问将所有的数合并成一个数所需要的最小代价。

  

  万恶的合并果子。

  这天的题目里面有5道题,其中4道题竟然全都是“合并果子”类题目。而解决这4道题的关键,就是先解决原版题目《合并果子》。

  悲剧的是,我在看这道题的时候,误以为是只有相邻的果子堆才能合并。于是先想到了区间DP,然后不断地改进、改进……比赛结束之后惊喜地发现只有10分,一问同学……

  这是我从今年7月份训练以来的第一次大失利,排名掉到了比赛总人数的一半以后。看错题这种低级失误,我已经很少犯了。以后一定要杜绝这种低级失误(丢了400分那种酸爽)。

  

【20150807】瑰丽华尔兹

  题目来源:NOI2005

  题目大意:给出一个有障碍的矩阵图 ( 1≤n,m≤2001\leq n,m \leq 200 ) 以及一个物体的初始位置。总时间 T ( 1≤T≤400001\leq T \leq 40000 ) 被分成了 k 段 ( 1≤k≤2001\leq k \leq 200 ),单个时间段内该物体只会向某个固定方向移动。每个时刻你可以选择物体向当前时刻所定的方向移动,抑或停止不动。问该物体在总时间后最多移动了多少格。

  

  比较典型的类搜索题。一年前做过一道此题的弱化版本(传送门),依稀记得当时只用个宽搜就过掉了,但是面对数据较强的此题,搜索无能为力。考试时尽管努力去想这道题更高级的解法,但没有想到较好的优化,于是作罢。

  

  正解是DP。定义 f[i][j][k]f[i][j][k] 表示当前走到的位置为 (i,j)(i,j) 且已走完前 kk 段时间后能移动的最大格子数。显然朴素做法是 O(2004)O(200^4) 的。但是因为在单个时间段里有固定的方向,针对这个方向我们就可以使用单调队列优化。

  举个例子:当前时间段向下移动时有 f[i][j][k]=f[i−x][j][k−1]+xf[i][j][k]=f[i-x][j][k-1]+x  那么固定 j,i 递增,单调队列中存放 f[x][j][k]−x, (1≤x≤i−1)f[x][j][k]-x,~(1\leq x \leq i-1),取队头为当前的最终决策,并维持单调队列递减(为什么?)。

  对于其他的方向只需要照葫芦画瓢就可以了。

  

【20150808】青蛙

  题目大意:一只青蛙从第 n 片荷叶开始,在 n 片连续的荷叶上跳跃 ( 1≤n≤200001\leq n \leq 20000 )。如果它在第 i 片荷叶上,那么它会选择 1~i 中的一片荷叶跳过去。问跳到第 1 片荷叶上的期望跳跃次数。

  

  应该说我对概率题最伤脑筋了,完全不会做(因为连基础的概率知识也没有掌握),考试时碰到这道题,直接弃疗。

  其实应该这么想:如果设 f[i]f[i] 为从第 i 片荷叶开始跳的期望跳跃次数,那么就有:f[i]=(∑i−1j=1f[j]+1)+f[i]if[i]=\frac{(\sum_{j=1}^{i-1}f[j]+1)+f[i]}{i}  即f[i]=∑i−1j=1f[j]i−1+1f[i]=\frac{\sum_{j=1}^{i-1}f[j]}{i-1}+1  时间复杂度可以做到 O(n)O(n)。

  看完题解突然觉得自己很弱渣……这么简单的东西怎么我就想不到?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: