2021牛客多校训练营1
D-Determine the Photo Position
签到题。
F-Find 3-friendly Integers
如果一个正整数存在一个连续的子串,满足子串是3的倍数,那么我们称这样的正整数为“3-友好”的。给你L和R(1<=L<=R<=1e18),求[L,R]中有多少个数是“3-友好”的。
签到题,显然3位及以上的数均为“3-友好”的,所以只需预处理1位数和2位数即可。
B-Ball Dropping
一个球体在空中落下,球心正好在一个空的等腰梯形的中心线上。请确定球是否会卡在梯形中或越过梯形。
小学数学题,推出边界条件的公式即可。
A-Alice and Bob
Alice和Bob玩取石子游戏。一开始有两堆石子,数量分别为n和m(1<=n,m<=5000),每次操作从其中一堆取走k(k>0)个石子,并从另外一堆取走s*k(s>=0)个石子。Alice先手,不能操作者输,问最后谁赢。
打表找规律。观察到对于每一个n,最多只有一个m可以使得Bob赢,于是问题转化为求这个m。
比赛的时侯,我们也对这个小结论做了一个简单的证明:
设能使Bob赢的m的唯一取值为f[n],现对m分类讨论:
1.若m>f[n],则Alice只需取m-f[n]个石子即可将局面变成n、f[n],而这是一个先手必输局面,因此Bob必输。
2.若m<f[n],则此时的m不可能使得Bob赢。否则,f[n]应取此时的m,而原来的f[n]就会变成第一种情况,这与f[n]的定义矛盾,因此Bob必输。
综上所述,对于每一个n,最多只有一个m可以使得Bob赢。
有了这个小结论之后,我们只需要预处理f[n]即可。对于每一个n,我们暴力枚举m,用f[2]、f[3]、...、f[n-1]这些必败局面(f[1]不存在),来check当前这个m是否是一个必胜局面(即是否能转移过去)。若不是,则当前这个m就是f[n]。
时间复杂度。
K-Knowledge Test about Match
给你一个序列a={0,1,2,…,n−2,n−1},再随机生成一个权值范围为0~n-1的序列b,你可以重新排列b,使得
最小。要求平均情况下和标准值偏差不能超过4%。
这个题在比赛的时候着实没想出来怎么搞(想了个贪心结果发现假了),比赛结束之后去看题解,发现题解里面写着这样一行字:
考察内容:贪心,乱搞,匹配。
结果还真有乱搞过去的,就双重循环枚举b序列中的每两个数b[i]、b[j],若交换b[i]和b[j]可以使得答案变小,就交换一下。
重复以上操作15轮左右就可以保证答案基本正确了。(听起来就十分乱搞)
std使用的贪心做法:从小到大枚举d,每次贪心去看是否存在两数差=d的数对,如果存在就暴力匹配上去。
H-Hash Function
给你一个长度为n(1<=n<=5e5)的数列a(1<=a[i]<=5e5),求最小的正整数seed,满足数列中的每个数%seed的结果都不一样。
容易发现,seed仅与数列中的每个数,两两之间的差值有关。因为两个数同余,就等价于这两个数的差值是模数的倍数。
因此,若我们可以知晓值域内,每个差值是否出现过(用一个数组标记)。那么,我们就可以从小到大枚举seed,看下seed的倍数们是否被标记过,若seed的倍数们都没被标记过,那么此时的seed就是ans。
问题的关键就在于,求出每个差值是否出现过。暴力去做是的,考虑使用FFT优化(比赛时还没学会FFT因而错失此题)。
我们考虑将已知信息转化为两个多项式的系数。记这两个多项式为a、b,用a[i]表示的系数,初始化为0(b同理)。
对于数列中的每个数x,我们将a[x]和b[-x+M]设为1(M为值域上限),这样对a和b做卷积后得到的c,我们考察一下c[M+d]的意义。若c[M+d]不为0,则必然至少存在一组p、q,满足p+q=M+d且a[p]和b[q]均不为0(考虑多项式乘法的实际意义),那这意味着什么呢?
对a而言,a[p]不为0意味着p是数列中的某个数;对b而言,b[q]不为0意味着M-q是数列中的某个数。而p+q=M+d,即p-(M-q)=d,这意味着这两个数的差值是d。换而言之,只要c[M+d]不为0,我们就可以直接断定差值d在值域内出现过!
这样,我们就可以在的时间内求出每个差值是否出现过了。
2021牛客多校训练营2
C-Draw Grids
签到题。
D-Er Ba Game
签到题,依题意模拟即可。(比赛时,输出中的某一个first不小心敲成了fisrt导致白白WA了一发)
K-Stack
构造题。你有一个1~n(1<=n<=1e6)的排列a,现在需要将a中的每个元素依次加入单调栈。已知若干时刻的单调栈大小,构造一个合法的序列a。
输出-1(无解)的情况就不多说了,讨论一定有解的情况。
由于题目中只给了部分时刻的单调栈大小,考虑将其余时刻的单调栈大小补齐。记siz[i]表示第i个时刻的单调栈大小,补齐的具体方法如下:
1.从后向前遍历一遍siz数组,若siz[i]存在,则将其值保存到一个变量tmp中;若siz[i]不存在,则令siz[i]=--tmp(若tmp<=0则不要赋值)。此时maybe还剩一部分siz没有赋值,于是转入第2步。
2.从前向后遍历一遍siz数组,若siz[i]存在,则将其值保存到一个变量tmp中;若siz[i]不存在,则令siz[i]=++tmp。
这样安排siz的好处是,a序列必然是由若干个单调递增的区间构成,并且由每个区间的第一个数构成的子序列必然是单调递减的(想一想,为什么)。因此,只需要从后往前依次安排每一段即可,时间复杂度O(n)。
I-Penguins
可爱的企鹅是一个小游戏,玩家控制两只企鹅。第一只企鹅位于一个迷宫的右下角,第二只企鹅位于另一个迷宫的左下角。企鹅可以向四个方向移动:上、下、左、右,但是如果它的去路被挡住了,或者它到达了边界,那么这次移动就被忽略了。
你可以操控其中任何一只企鹅进行移动,但这只企鹅移动一步的同时,另一只企鹅会向反方向移动一步(例如第一只企鹅向左移动了一步,则第二只企鹅会向右移动一步)。如果第一只企鹅到达右上角的同时,第二只企鹅也到达了左上角,那么你就赢了。
计算赢得游戏所需的最小移动次数,并输出第一只企鹅的移动轨迹。若最小移动次数对应的移动轨迹不唯一,请输出字典序最小的那个。数据保证答案存在。
注意:当一只企鹅到达目的地而另一只没有到达时,已经到达目的地的企鹅可能仍会离开目的地。
裸的bfs,没什么好说的。
F-Girlfriend
空间内有6个点,满足,
。求
、
各自运动轨迹围成的空间体的体积交。
实际上是个球交,看成两个球缺的体积和即可。利用积分法可以轻易地得到球缺的体积公式:
,其中R是球的半径,H是球缺的高。
G-League of Legends
To be continued...
L-WeChat Walk
To be continued...
2021牛客多校训练营3
J-Counting Triangles
签到题,装模做样地给了一段生成数据的代码,一开始还以为要观察代码从而得出什么结论,最后发现真的只是个生成随机数的代码罢了......(差点签不上到)
题意倒是很简单,就是给你一幅完全图,每条边非黑即白,问你有多少个同色三角形。
正难则反,考虑计算异色三角形的个数。发现以图中某个点作为顶点的异色三角形的数量,就是从这个点出发的黑边数*从这个点出发的白边数。求出每个点的异色三角形的数量,加起来除以2即可(每个异色三角形被重复计算了两遍)。
比赛的时候,一度以为上面的做法不是正解,然后研究生成数据的代码研究了好久......
B-Black and white
给你一个n*m(1<=n,m<=5000)的棋盘,每个格子有一个染色代价c[i][j]。任意两行与任意两列相交,交出来的4个格子中,如果有3个格子已经被染色,那么你就可以免费将第4个格子染色。问最小染色总代价。
对一个格子(i,j)染色,相当于花费c[i][j]的代价,在所在行i与所在列j之间连一条无向边;若某个格子(i,j)所在行i和所在列j已经连通了,那么这个格子就会免费被染色。因此整个棋盘被染色,等价于行与列全部连通。在行与列的完全二分图上跑最小生成树即可。
比赛的时候,隐隐约约感觉到这题像个最小生成树,写了个贪心选点+并查集合并行与列,结果T飞了。比赛结束之后才反应过来,这不就是kruskal么......然而完全图上跑kruskal等于找死,补题的时候改成prim就AC了。
E-Math
To be continued...
F-24dian
给你n(1<=n<=4)组卡片,每组卡片13张,第i张卡片上的数字为i(1<=i<=13)。你可以将卡片按任意顺序排列,在任意两张卡片之间添加+或-或*或/,并添加任意数量的括号,使得表达式有效且其值等于m。
一个合法解是指一个卡片集合,满足这个卡片集合至少存在一种排列,可以在添加运算符和括号后得到m。并且,对于这个卡片集合的任何一个能够得到m的排列,对于这个排列的任何一个能够得到m的表达式,都必须在运算过程中包含分数(即非整数)。
求所有的合法解,并按字典序输出。
本题的难点在于正确理解题意。(我不会告诉你我们前前后后想了5种题意,并且每次都认为这次的题意是真的)
确保正确理解题意之后,我们就可以开始dfs了,其中需要注意的细节如下:
1.题目中所说的分数,指的是比值为非整数的分数,例如4/2就不算比值为非整数的分数。
2.合法解指的是集合而不是排列。例如,2、4、10、10((2+4/10)*10=24)和4、10、2、10((4/10+2)*10=24)属于一种合法解而不是两种合法解。
3.若一个集合存在多种排列可以得到m,而某一种得到m的排列在运算过程中没有包含非整数,那么这个集合不是一个合法解。
例如,集合{1,5,7,10}存在多种排列可以得到24,一种是1、7、5、10((1+7/5)*10=24),在运算过程中包含非整数7/5;另一种是5、7、1、10(5*7-1-10=24),在运算过程中没有包含非整数。因此,集合{1,5,7,10}不是一个合法解。
4.若一个排列存在多种表达式可以得到m,而某一种得到m的表达式在运算过程中没有包含非整数,那么这个排列所在的集合不是一个合法解。
例如,排列1、5、3、9存在多种表达式可以得到24,一种是(1+5/3)*9=24,在运算过程中包含非整数5/3;另一种是(1-5)*(3-9)=24,在运算过程中没有包含非整数。因此,集合{1,3,5,9}不是一个合法解。
5.当1<=n<=3时是必然无解的(证明见附录1),因此只需考虑n=4的情况即可。
至此,我们就愉快地做完了这道毒瘤的搜索题。
附录1:1<=n<=3必然无解的证明
1.当n=1或n=2时,表达式中不可能存在比值为非整数的分数,故无解。
2.当n=3时,若某个可以得到m的表达式中存在非整数,那么我们必然可以调整表达式的运算顺序,使其不存在非整数(例如3/(1/8)=24,等价于3/1*8=24)。而这与题目要求不符,故无解。
附录2:赛场上想的5种题意
1.在n个数字之间添加运算符和括号,使其等于m即可。合法解的要求是表达式必须包含分数。
2.在1的基础上,要求分数必须是比值为非整数的分数。
3.在2的基础上,规定合法解是一个集合而不是一个排列。
4.在3的基础上,要求分数必须是真分数。
5.在3的基础上,要求集合的每个排列的每个表达式,都必须在运算过程中包含非整数。
2021牛客多校训练营4
F-Just a joke
签到题。
I-Inverse Pair
给你一个1~n(1<=n<=2e5)的排列,对于每一个数,你要么对其+1,要么不变,求最小逆序对数。
考虑什么时候+1可以使得答案变小。不难看出,每个数a[i]对答案的贡献,只与位于i后面且等于a[i]的数的个数num1,以及位于i前面且等于a[i]+1的数的个数num2有关。若num1<num2,则对a[i]进行+1操作是值得的,否则不值。
具体实现上,我们用vector存储下标,这样就可以方便地维护num1和num2。若选择对a[i]进行+1操作,则从a[i]所在的vector中删除i,并将i加入a[i]+1所在的vector。最后使用归并排序/树状数组求逆序对即可,时间复杂度。
std使用的做法:考虑建一张图,若x在x+1后面则连边(x,x+1),最后会得出若干条链,一条长度为L的链,我们最多用它减少L/2个逆序对。时间复杂度。
J-Average
你有一个n*m(1<=n,m<=1e5)的矩阵W,这个矩阵是用两个序列a、b生成的,W[i][j]=a[i]+b[j](1<=i<=n,1<=j<=m,0<=a[i],b[j]<=1e5)。你需要找到W的一个子矩阵,满足子矩阵的高度不小于x,且宽度不小于y,求这样的子矩阵的最大平均值。
直接把W求出来是不现实的,考虑推一下平均值的式子:
据此我们可以看出:W的子矩阵的最大平均值,就是由a和b分别求最大平均值相加得到的。
于是问题转化成了 : 找a的一个长度至少为x的平均值最大的子区间,和b的一个长度至少为y的平均值最大的子区间。
二分答案,考虑如何check。对于一个平均值mid,令c[i]=a[i]-mid,若c存在一个子区间,满足子区间和>=0;则等价于a存在一个子区间,满足子区间平均值>=mid。这个用前缀和即可O(n)计算,总时间复杂度。
C-LCS
To be continued...
E-Tree Xor
To be continued...
2021牛客多校训练营5
H-Holding Two
签到题。
B-Boxes
一道很好玩的数学题。
你面前有n(1<=n<=1e5)个盒子,你知道每个盒子里面有一个白色或黑色的球,且球为白色和球为黑色的概率相等,均为1/2。你想要得知每个盒子中的球是什么颜色。你有两个选择:
1.花费w[i]的代价打开第n个盒子,这样你就可以知道第i个盒子中的球是什么颜色。
2.花费C的代价询问先知,先知可以告诉你尚未打开的盒子中,黑白球各有多少个。
求得知每个盒子中的球的颜色,所需要花费的最小代价的数学期望。
首先要明确一件事:要么不问先知,直接花费sum(w)的代价打开所有盒子;若要询问先知,必然选择在第一次开箱前花费C的代价询问先知,否则不优。
两种策略的代价的数学期望如下:
1.直接全部打开,。
2.将w[i]升序排列,先花C的代价询问先知,接下来就相当于一个随机01序列从前往后开,开到一个后缀全是同色的为止。不开第i个盒子的概率为,故
。
最小代价的数学期望ans=min(ans1,ans2)。
K-King of Range
给你一个长度为n(1<=n<=1e5)的序列a(1<=a[i]<=1e9),有m(1<=m<=200)个询问。每次询问给你一个k,问你有多少个子区间,满足子区间的极差严格大于k。
一个比较直接的思路是:对于每一个左端点L,二分右端点R,用ST表O(1)查询[L,R]最值。这样可以做到单次询问 ,总时间复杂度
,不能通过此题,考虑优化。
对于一个左端点L=i,记满足条件的最小右端点为R[i],显然R[i]是单调不减的。于是无需二分右端点R,只需使用双指针维护L和R即可。这样可以做到单次询问O(n),总时间复杂度O(mn),可以通过此题。
2021牛客多校训练营6
I-Intervals on the Ring
签到题,输出每一段未被覆盖的区间的补即可。
F-Hamburger Steak
有n(1<=n<=1e5)个汉堡排和m(1<=m<=1e5)个锅,给出每个汉堡排需要煎的时间t[i](1<=t[i]<=1e9)。一个汉堡排可以在一个锅中煎好,也可以分成两次在两个锅中煎好。一个锅同一时刻只能煎一个汉堡排,一个汉堡排同一时刻只能放到一个锅中。问你最快要多久才能煎完所有汉堡排,并输出一种方案。
比赛的时候,我们感觉一个汉堡排在两个锅中煎是没必要的,于是写了个贪心,将t[i]降序排列,每次将当前的汉堡排放入当前总耗时最短的锅即可。
其实,这个贪心是一个相当假的算法,但是由于我们一直找不到反例,所以被我们误以为是代码写挂了才导致的WA。接着,我们又调了好久代码,不仅浪费了很多时间,也因此影响了比赛心态。
比赛结束后找到的一组反例:
3 2
7 5 4
贪心做法会输出9(5+4),而正确答案是8(5+3=4+4)。这里就是把第1块汉堡排放在两个锅中煎了,单位时间(0,4]在第2个锅中煎, 单位时间(5,8]在第1个锅中煎。
这道题的正确做法是,假设我们已经知道了最小耗时T,就可以贪心地将每个锅的时间T依次分配给每个汉堡排,当前这个锅没煎完的部分再由下个锅煎即可。
为了满足题目要求,我们需要保证所有锅的时间和>=所有汉堡排的时间和,以及耗时最长的汉堡排不会在同一时刻分到两个锅中(耗时小于它的自然也就满足条件),于是最小耗时为。
PS:假设题意真的是每个汉堡排只能在一个锅中煎,那么这道题就变成了经典的“装箱问题”,而这是一个NP困难问题,目前还不存在靠谱的多项式复杂度的做法。
H-Hopping Rabbit
To be continued...
2021牛客多校训练营7
I-xay loves or
签到题。
H-xay loves count
给你一个长度为n(1<=n<=1e6)的序列a(1<=a[i]<=1e6),求有多少个三元组(i,j,k),满足。
签到题。我们先枚举,此时合法的
就仅剩
种了,这个时候再枚举
,即可算出
。时间复杂度为调和级数,即
。
F-xay loves trees
给你两棵有根树,每棵树都有n(1<=n<=3e5)个结点,并且根结点均为1。你要找到最大的点集S,满足:
1.在第一棵树上,,都满足u是v的祖先,或v是u的祖先;并且S是连通的。
2.在第二棵树上,,都满足u不是v的祖先,且v不是u的祖先。
输出S的大小。
比赛时想到的做法:由于直接去求S的大小比较困难,考虑二分答案。
记第一棵树为A树,第二棵树为B树。由于S中的点,在A树上构成了一条自上而下的链,不难想到在A树中选点,接着在B树中check它们是否具有祖先关系。
我们在A树中每选一个点x,就必须在B树中给x的子树打上标记,被标记的点将不能再被选择。暴力去做是O(n)的,但是注意到x的子树,在B树的dfs序上是一个连续的区间,因此用线段树优化就可以做到了。
当在A树中选好点后(即选好链后),只需在线段树上查询一下整个区间的最大值mx,若mx<=1(表示每个点被标记了不超过1次),则当前这个点集是合法的;若mx>1(表示某个点被标记了超过1次),则当前这个点集是不合法的。
这样,对于一个大小siz,我们只需在A树上进行一遍dfs,在到达某点的时候打上标记(区间+1),在链长度等于siz的时候check一下当前点集是否合法,在离开某点的时候撤销标记(区间-1),就可以知道siz是否成立了。
时间复杂度,但是由于常数因子等原因,此题未能在比赛中AC。
赛后发现,其实这题根本无需二分答案,只需在遍历A树的时候,用双指针维护链的两端L、R即可。
具体来讲:R每次向下移动一步,若发现当前点集是合法的,则更新ans;若发现当前点集是不合法的,则令L向下移动一步即可。即使当前点集依旧是不合法的也没关系,因为令L移动更多步显然不会使ans变得更优。
这样做的时间复杂度为,可以通过此题。
附录1:std使用的主席树做法
首先是一些记号的说明:
1.fa[x]表示x在A树中的父亲。
2.dep[x]表示x在A树中的深度。
3.dfn[x]表示x在B树中的dfs序。
4.siz[x]表示x在B树中的子树大小。
5.h[x]表示x作为A树中的链最深点时,链最浅点的深度。
在A树上进行dfs,到达一个点x的时候,在fa[x]的基础上把x在B树中的子树[dfn[x],dfn[x]+siz[x]-1]覆盖成dep[x]。
这样,我们只需在fa[x]的主席树上,查询区间[dfn[x],dfn[x]+siz[x]-1]的最大值mx。显然,mx就是最近的一次祖先覆盖,那个祖先在A树中的深度。因此h[x]=mx+1,用h[x]更新ans即可。
时间复杂度。
2021牛客多校训练营8
E-Rise of Shadows
签到题。
A-Ares, Toilet Ares
签到题,只不过题意相当难懂。在提交了6发罚时之后,终于明白题意是求
,除此以外的各种变量根本没用。
K-Yet Another Problem About Pi
To be continued...
D-OR
给你两个长度为n-1(2<=n<=1e5)的序列b、c。一个长度为n的序列a被认为是美丽的,当且仅当,有
,
,且每个
都是非负整数。
求美丽的序列的个数。
注意到x+y=x&y+x|y,所以题目相当于给出了a序列,每两个数与和或的结果。因此,只要确定在2进制下的每一位,那么
~
就可以被唯一确定了。
依次枚举的每一位取0/1,然后check一下是否成立。若0/1都成立,则ans*=2;若0/1只有一个成立,则ans不变;若0/1都不成立,则ans=0。
时间复杂度O(n)。
J-Tree
To be continued...
2021牛客多校训练营9
H-Happy Number
签到题。
C-Cells
在二维平面上有n个点,第i个点的坐标是(0,)(保证
互不相同)。在每个点上有一辆卡车,第i辆卡车的目的地是(i,0)。每辆卡车可以从(x,y)移动到(x+1,y)或(x,y-1),求使n辆卡车的运动轨迹均不相交(即没有公共点)的方案数。
打表找规律。先研究一些比较简单的情况:
1.当n=1时,显然。
2.当n=2时,打表结果如下:
1 | 2 | 3 | 4 | 5 | |
0 | 1 | 3 | 6 | 10 | 15 |
1 | 3 | 8 | 15 | 24 | |
2 | 6 | 15 | 27 | ||
3 | 10 | 24 | |||
4 | 15 |
观察得到的规律如下:
(1)表具有上下对称性,即与
的结果是一样的。
(2)当=0时,
。
(3)当=1时,
。
(4)当=2时,
。
若将第(3)条规律的ans写成,则(2)(3)(4)可以总结为:
。
经验证,这就是n=2时的ans。