假期集训Day 3 #2020011700047-71

知识点目录

1 模拟

模拟是对真实事物或者过程的虚拟。模拟要表现出选定的物理系统或抽象系统的关键特性。模拟的关键问题包括有效信息的获取、关键特性和表现的选定、近似简化和假设的应用,以及模拟的重现度和有效性。可以认为仿真是一种重现系统外在表现的特殊的模拟。(来自百度百科)
顾名思义,模拟就是我们去用代码实现某种操作,他怎么说你就怎么做,他要求你做什么你就做什么。
模拟是竞赛中最基础的一项基本功,对思想难度要求不高,主要考察选手的代码能力

1 水仙花数

2020011700047

题意描述

输出所有的"水仙花数".所谓"水仙花数"是指这样的一个三位数:其各位数字的立方和等于该数本身。
例如:\(371\)是一个"水仙花数",\(371=3^3+7^3+1^3\).

题解

对于一个三位数\(x\)
百位:\(\dfrac{x}{100}\)
十位:\(\dfrac{x}{10}\mod10\)
个位:\(x\mod 10\)
判断这三个数的立方和是否为\(x\)即可

2 河伯阵型

2020011700048

题意描述

河伯最近在打一个叫魔兽争霸3的游戏,这个游戏可以控制兵推掉对面的老家,而这个游戏阵型很重要,河伯现在要排成一个菱形,所以请你帮河伯排一下阵型

输入

3 ^

输出

  ^
 ^^^
^^^^^
 ^^^
  ^

题解

?---?

3 USACO-1.1.2-Greedy Gift Givers

2020011700049

题意描述

一共有\(n\)个人要互相送礼物,每个人准备了一些钱来给自己想送的人买礼物。同一个人送出的礼物都是等价的,多余的钱会自己留下,求n个人送完礼物之后,每个人都赚了或者亏了多少钱。

题解

?---?

2 贪心

贪心算法是指在对问题求解时,总是做出在当前看来是最优的决策
换言之,就是不从全局最优方面考虑,只考虑局部最优情况
贪心算法有时可以得到全局的最优解,这取决于贪心的策略

一个正确贪心的例子

排队接水问题

\(N\)个小朋友来接水,每个人接水要用\(a_i\)的时间,求最小的等待总时间。等待总时间是指所有小朋友的等待时间之和。显然这是一个小学奥数中的简单题。我们让接水时间短的人排在前面,时间长的人排在后面,可以证明这种方案是正确的。

一个错误贪心的例子

\(N\)个小朋友,\(M\)块糖,给出一个二维数组,其中\(a_{i,j}\)代表第\(i\)个小朋友获得\(j\)块糖之后的喜悦值,要求求出所有小朋友的喜悦值之和最大是多少
可以想到一种贪心方式是:对于每块糖,我们选择获得这块糖之后对答案贡献最大的小朋友,把糖分给它
反例:

2 3
1 100

所以我们可以得出,不是所有的情况都可以贪心,一般来说,当我们试图用贪心做法来解决一道题的时候,最好能先证明贪心的正确性,否则只靠猜测一般来说是不正确的。
下面几道例题并不全是可以贪心的。如果大家认为可以贪心,请说明你的贪心策略,最好能尝试证明贪心的正确性。

4 最大排列

2019011700050

题意描述

有一个长度为\(N\)的序列,每个元素互不相同,现在给你\(K\)次操作机会(可以不用完),每次可以交换相邻两个数,求在这种条件下,你能交换出的字典序最大的序列是什么,\(N\leq 5000\).

题解

贪心可做√
由于要求字典序最大,也就是说我们的目标是:让第一个数尽可能大,在这个基础上让第二个数尽可能大…所以每次我们在可选的范围内找到一个最大的数,把他交换到前面,然后处理下一位即可。

5 运输

2020011700051

题意描述

黑板上N个正整数,给出一个正整数K每次你可以擦掉黑板上的两个数A,B,然后在黑板上写下(A+B)/K向下取整的值,直到只剩下一个数,问剩下的数最少是多少,N<=10000.

题解

贪心可做√
错误的贪心策略:从大到小依次擦掉。可以举出反例,所以我们在考场上应该多出几组数据来尝试卡掉自己的贪心策略
正确的贪心策略:每次选取最大的两个数擦掉

6 防御导弹[NOIP 1999]

2020011600052

题意描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截 系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。已知敌国每颗导弹的高度,问:用一套系统最多能拦截多少导弹?如果要拦截所有导弹最少要配备多少套这种导弹拦截系统?

题解

第一问贪心不可做×
可以证明所有关于这道题的贪心做法都是错误的。都可以举出反例(最长不下降子序列LIS)
第二问贪心可做√
贪心策略:每个导弹能打就打

7 Cow Acrobats

2020011700053

题意描述

\(N\)头牛,每头牛有体重和力量两个属性,他们要在一起叠罗汉,每头牛的危险值\(=\)它上面所有牛的体重之和\(-\)这头牛的力量,求所有牛的最大危险值最小是多少

题解

贪心可做√
贪心策略:把所有牛按照体重+力量从小到大排序,小的在上面
正确性证明:
对于一种排列方案,如果我们可以找到相邻的两头牛\(i,j\)\((i\)在上\()\)使得交换它们的位置之后答案变小,则这种方案一定不是最优解
我们考虑不想出现这种情况需要满足什么,设体重为\(a\),力量为\(b\),上面所有牛的体重之和为\(W\),则有:
\(\max(W-b_i,W+a_i-b_j)\leq \max(W-b_j,W+a_j-b_i)\)
化简之后得\(a_i+b_i\leq a_j+b_j\)
也就是说,若不按照\(a_i+b_i\)从小到大进行排列则一定不是最优解
而按照\(a_i+b_i\)从小到大排列只有一种方案(相同的是等价的),所以这就是最优解

3 二分

给你一个一次函数(\(y=kx+b\)),求函数的零点
给你一个单调函数的解析式,例如\(y=x^3+\ln x+2^{x-10}\),求函数的零点

二分法可以用来解决这一系列具有单调性质的题(不一定是求单调函数的零点)
其实在小学奥数中就用到了二分法,例如手动开根号,再比如猜数游戏
二分的具体过程就是先取一个中间值,判定一下正确答案在哪边,然后接着再二分,直到找到答案为止
二分相对于暴力枚举来讲,判定次数会显著变少,具体来说,如果暴力枚举期望是\(O(N)\)次,那么二分只需要\(O(\log N)\)次就可以得出答案

怎么用代码实现?

while(r-l>eps)
{
	mid=(l+r)/2;
	if(f(mid)>0) r=mid;
	else l=mid;
}
while(l<r)
{
	mid=(l+r)/2;
	if(f(mid)>0) r=mid;
	else l=mid+1;
}

8 派

2020011700054

题意描述

我的生日要到了!根据习俗,我需要将一些派分给大家。我有\(N\)个不同口味、不同大小的派。有\(F\)个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。
我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。
请问我们每个人拿到的派最大是多少?每个派都是一个高为\(1\),半径不等的圆柱体。

题解

二分每个人拿到的派的大小
然后整体扫一遍\(N\)个派,由于每个人派的大小已知,那么每个初始的派能切成的块数就也能知道了
检验一下这些派够不够分,如果不够,说明每个人拿的派太大了,往小了二分,如果够,说明每个人可能还可以拿更多的派,往大了二分

9 最大值最小化

2020011700055

题意描述

把一个包含n个正整数的序列划分为\(m\)个连续的子序列(每个正整数恰好属于一个序列)。设第\(i\)个序列的各数之和为\(S(i)\),你的任务是让所有\(S(i)\)的最大值尽量小。
例如序列\(1,2,3,2,5,4\)划分成\(3\)个序列的最优方案为\(1,2,3|2,5|4\),其中\(S(1)\)\(S(2)\)\(S(3)\)分别为\(6,7,4\),最大值为\(7\);如果划分成\(1,2|3 ,2|5,4\),则最大值为\(9\),不如刚才的好。
\(n\leq 10^6\),所有数之和不超过\(10^9\)

题解

先二分一下最大值是多少
这个值是每一段总和的上限,然后贪心,只要总和在这个限度内就不断地往里添加后面的数,直到不能添加为止,那么这些数就组成了一段。扫完所有的数之后,看一看划分出了几段。
如果段数\(>m\),说明这个最大值设得太小了,应该变大,\(l=mid+1\);否则说明最大值还有可能变小,\(r=mid\)

10 排干水塘

2020011700056

题意描述

公园里有\(n\)个水塘,需要把这\(n\)个水塘中的水排干,水塘中的水在自然条件下\(1\)个单位的时间可以蒸发\(A\)升水。现在买了\(1\)台抽水机,使用抽水机可以让你用\(1\)个单位的时间使每个水塘除开自然蒸发的\(A\)升水外,还可抽\(B\)升水,但在\(1\)个单位的时间内只能对\(1\)个水塘使用。
要你求出排干所有水塘的最少时间(水塘中的水为\(0\)时为排干)。

题解

二分一下时间\(T\)
也就是说,你可以视为每个池塘先蒸发了\(A\times T\)升水,之后就不再蒸发,然后你开始使用抽水机
我们可以在\(O(N)\)时间内算出用抽水机抽完剩下的水要花多少时间。如果时间\(>T\),说明时间不够,\(T\)应该放大
否则说明时间可能更小

11 序列积第\(n\)小元素

2020011700057

题意描述

给出两个长度为\(n\)的正整数有序数组\(A\)\(B\), 在\(A\)\(B\)中各任取一个, 可以得到\(n\times n\)个积. 求第\(n\)小的元素。\(n\leq 100000\)

题解

二分答案
判定有多少乘积小于这个答案就可以继续二分
但是怎么判定呢?
由于两个数组都是有序的,所以A数组中可行的乘积对应B数组一定是从头开始的一段序列,并且范围逐渐变小。这样我们\(O(N)\)扫一遍,用一个指针维护一下\(B\)数组合法位置就可以了

三分法

给你一个一次函数(\(y=x^2+bx+c\)),求函数的零点
与二分法类似,三分法可以用来解决具有单峰性质的题
三分的具体过程就是先取两个中间值,分别位于\(\dfrac{1}{3}\)\(\dfrac{2}{3}\)处,根据单峰性判定一下正确答案在前\(\dfrac{2}{3}\)还是后\(\dfrac{2}{3}\),然后接着再三分,直到找到答案或答案的近似值为止
二分法每次把答案范围缩小一半,三分法每次把答案范围变为原来的\(\dfrac{2}{3}\),他们的时间复杂度都是\(O(\log n)\)

12 传送带[Bzoj1857]

2020011700058

题意描述

在一个\(2\)维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段\(AB\)和线段\(CD\)。小y在\(AB\)上的移动速度为\(P\),在\(CD\)上的移动速度为\(Q\),在平面上的移动速度\(R\)。现在小y想从\(A\)点走到\(D\)点,他想知道最少需要走多长时间?

题解

三分套三分
小y走的路径一定是三条线段组成的折线
如果把离开\(AB\)线段的点设为\(x\),到达\(CD\)的点设为\(y\),总时间设为\(z\),那么\(z\)是关于\(x,y\)的二元函数
可以证明这个函数形如一个山丘,也就是说可以先三分\(x\)再三分\(y\)求出\(z\)的最值

4 分治

分治就是“分而治之”,他可以把一个复杂的问题简单化,从全局变成局部,逐渐缩小问题的规模,更加高效的解决问题
怎么可以变得高效?
快速排序、归并排序,都是用了分治的思想把时间从\(O(N^2)\)变成了\(O(N\log N)\)

13 逆序对

2020011700059

题意描述

给你个长度为\(N\)的序列,求这个序列的逆序对数量,\(N\leq 100000\)

题解

分而治之
直接暴力求的话,显然时间复杂度是不可接受的
我们不妨转换一下,分而治之
把整个数列劈成两半
则总的逆序对数量\(=\)左半部分逆序对数量\(+\)右半部分逆序对数量\(+\)左边的数比右边大的对数
前两项我们可以递归求解,最后一项我们可以在归并排序的同时稍加处理,\(O(N)\)计算出来
这样时间复杂度与归并排序一样,都是\(O(N\log N)\)

14 快速幂

2020011700060

题意描述

给你\(A,B,\)C,求\(A\)\(B\)次方模\(C\)的余数
\(A,C\leq 10^9,B\leq 10^{18}\)

题解

这是一个非常典型的分治例子
我们可以想像一下小学的时候我们如何计算2^16
\(2^{16}=4^8=16^4=256^2=65536\)
那如何计算\(2^{18}\)呢?
\(2^{18}=4^9=4\times 4^8=4\times 16^4=4\times 256^2=4\times 65536=262144\)
快速幂也是如此

15 棋盘覆盖

2020011700061

题意描述

相传在一个国家,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主这一个方格不能用地毯盖住,毯子的形状有所规定,只能有四种选择(如下所示):

并且每一方格只能用一层地毯,迷宫的大小为\((2^K)\times (2^K)\)的方形。
请你给出一种方案。

题解

分而治之
直接做好像并不可行,我们考虑逐渐把问题简化
先假设迷宫是一个\(2\times 2\)的方格,那么方案就很简单了:把公主没站的三个格子铺上地毯就OK了
现在想\(4\times 4\)的方格,我们把它划分成\(4\)\(2\times 2\)的方格,公主必然站在其中之一,所以那个\(2\times 2\)的方格的铺地毯方式就可以递归求出了。对于其他三个\(2\times 2\)的格子,我们先铺一个跨过他们三个的地毯,然后把这块地毯想象成三个公主,我们就可以递归求解了
接着再想\(8\times 8\)的方格,我们把它划分成\(4\)\(4\times 4\)的方格,公主必然站在其中之一,所以那个\(4\times 4\)的方格的铺地毯方式就可以递归求出了。对于其他三个\(4\times 4\)的格子,我们先铺一个跨过他们三个的地毯,然后把这块地毯想象成三个公主,我们就可以递归求解了

16 第\(k\)小元素

2020011700062

题意描述

给你一个长度为\(N\)的序列,要求你求出其中的第\(k\)小元素
\(1\leq K\leq N\leq 2000000\)

※不可以直接排序再找第\(k\)小,这道题只允许\(O(N)\)算法

题解

分而治之
类似快速排序,我们先随机找到一个值,然后扫一遍整个序列,这样可以统计出比他大的数的个数\(X\)和比他小的数的个数\(Y\),以及跟他相等的个数\(Z\),并按照\(YZX\)的顺序重新排列分为三部分
如果\(K\leq Y\),那我们不用管后部分,第\(K\)小元素一定在这些数当中,递归即可
如果\(Y<k\leq Y+Z\),那这个元素就是第\(K\)
如果\(Y+Z<k\),那我们不用管前部分,第\(K\)小元素一定在后面的那些数中,我们要找那\(X\)个数中的第\(K-(Y+Z)\)个元素
由于值是随机选取的,我们可以认为他把原数列分成差不多相等的两部分
所以\(T(N)=O(N)+T(\dfrac{N}{2})\),算法是\(O(N)\)

预告

更多以后可能会用到的分治
矩阵乘法快速幂加速递推
CDQ分治
整体二分
快速傅里叶变换
快速沃尔什变换
莫比乌斯变换
辛普森积分

5 递推

递推是指根据之前算出的值逐步计算出下一个值
这是学习动态规划之前必须弄明白的一个事情
实际上递推≈简单的动态规划

17 汉诺塔

2020011700063

题意描述

汉诺塔由编号为1到n大小不同的圆盘和三根柱子\(a,b,c\)组成。开始时,这\(n\)个圆盘由大到小依次套在\(a\)柱上,如图所示。要求把\(a\)柱上\(n\)个圆盘按下述规则移到\(c\)柱上:
(1)一次只能移一个圆盘,它必须位于某个柱子的顶部;
(2)圆盘只能在三个柱上存放;
(3)任何时刻不允许大盘压小盘。

将这\(n\)个盘子从\(a\)柱移动到\(c\)柱上,最少需要移动多少次?

题解

设移动\(n\)个盘子所用步数为\(f[n]\)
我们可以将\(n\)个盘子的移动步骤划分为:
1.先将前\(n-1\)个盘子移动到\(b\)
2.把最大的盘子移动到\(c\)
3.再把\(n-1\)个盘子移动到\(c\)
第一步和第三步都需要用\(f[n-1]\)
所以\(f[n]=2\times f[n-1]+1\)

18 放球问题

2020011700064

题意描述

A.有\(n\)个不同的球放要在\(m\)个相同的盒子,不允许有空盒子,问有多少种放置的方法?
B.有n个相同的球要放在m个相同的盒子里,可以有空盒子,问有多少种放置方法?

题解

(A)f[i][j]=f[i-1][j-1]+j*f[i-1][j]
(B)f[i][j]=f[i][j-1]+f[i-j][j]

19 核电站问题

2020011700065

题意描述

一个核电站有\(N\)个放核物质的坑,坑排列在一条直线上。
如果连续\(3\)个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质。
现在,请你计算:对于给定的\(N\),求不发生爆炸的放置核物质的方案总数。

题解

\(f[i][j]\)表示前\(i\)个坑最后连续放了\(j\)个的方案数
则有\(f[i][0]=f[i-1][0]+f[i-1][1]+f[i-1][2]\)
\(f[i][1]=f[i-1][0]\)
\(f[i][2]=f[i-1][1]\)

20 删数问题

2020011700066

题意描述

小明现在有\(n\)个不同的正整数\(X_1,X_2,…X_n\)排成一行。
小明每次可以将左边或右边删掉连续的若干个数(只能从两边删数)。
每次删数可以得到一个值,若删除从\(i\)\(j\)的数(\(i < j\)),则得到的价值为\(|X_i-X_j|\times (j-i+1)\)
若只删除一个数(\(i=j\)),则得到的价值为\(X_i\)
现在小明想使得到的价值总和最大,请你帮他计算一下,这个最大值是多少?

题解

删数相当于把序列分段
设把前\(i\)个数分段后的最大价值为\(f[i]\)

则有\(f[i]=\max(f[j]+V(j+1,i)),0\leq j<i,V(a,b)\)代表从\(a\)\(b\)的划分价值

21 凸多边形划分

2020011700067

题意描述

在一个凸\(n\)边形中,通过不相交于\(n\)边形内部的对角线,把\(n\)边形拆分成若干三角形,问有多少种拆分方案。
例如五边形有如下五种拆分方案。

题解

\(f[i]\)表示凸i边形的划分方案
我们考虑如何求\(f[i]\)
我们随便选择一条边,这条边一定在一个三角形上
所以我们可以枚举剩下的那个顶点,这样划分完了之后,除了这个三角形,原来的多边形被划分成了两个(一个)小的凸多边形,接着划分的方案数就等于这两个方案数的乘积

22 HAOI2009 逆序对数列

2020011700068

题意描述

\(1\)~\(n\)的所有排列中有多少种逆序对为\(k\)的方案数,\(n\leq 1000,k\leq 1000\)

题解

\(f[i][j]\)表示\(1\)~\(i\)的排列逆序对为\(j\)的方案数
我们怎么递推呢?
我们假设\(1\)~\(i-1\)已经排好了,现在要把\(i\)插进去
对于\(i\)个可插的位置,分别会产生\(0,1,2..i-1\)个新的逆序对
所以递推式子为

其实上一道题已经算动态规划了
动态规划说白了就是难一点的递推,难点就在于怎么设状态,怎么写转移方程…
多做做递推的题之后,刷DP就会易如反掌

6 构造法

所谓构造法是指当一个问题有1个或多个解,而我们找到了直接生成其中一个解的办法,或者找到了从一个解生成下一个解的办法时,直接通过构造而生成解,从而避免去搜索穷举产生解。

23 全序列给定数

2020011700069

题意描述

给定一个数\(x(0 \leq X \leq 10^6)\),求一个数\(a ( 0\leq a \leq 10^{16})\)使得 :
1.\(a\) 是 \(x\) 的倍数
2.\(a\)的十进制表示包含\(0\)\(9\)
举个例子, 如果 \(x = 1\), 那么 \(9182736450\) 就是一个符合条件的\(a\)
给出任意一个解即可

题解

构造
要求答案小于\(10^{16}\),不妨直接令\(a\)的前\(10\)位是\(1234567890\),设\(a%x=t\),只要使\(a\)的后\(6\)位为\((x-t)\)即可

24 兔子值班

2020011700070

题意描述


给出一种方案,\(n\leq 999,n\)是奇数

题解

奇妙的构造
总共有\(C(n,2)\)对兔子,每次值班会对3对产生贡献,那么答案的上界就是\(C(n,2)\)
的确存在达到上界的方案

for (int i=1;i<=(n>>1);i++) 
	for (int j=1;j<=n;j++) 
		printf("%d %d %d\n",j,(j+i-1)%n+1,(j+i+i-1)%n+1);

长度为\(3\),跨度小于\(n\)的所有等差数列(循环意义下)

25 最短路径

2020011700071

题意描述


提示:一个图可以一笔画当且仅当奇度数的点有\(0\)个或\(2\)

题解

分类讨论
不妨设\(x\leq y\leq z\)
\(x=1\),平面
\(x=2\),高度为1
\(x=3\),只有顶点和面上的点度数为奇

posted @ 2020-01-17 07:13  刘子闻  阅读(266)  评论(0编辑  收藏  举报