退役前的做题记录5.0
出于某种原因新开了一篇。
[CodeChef]Querying on a Grid
对序列建立分治结构,每次处理((l,mid,r))时,以(mid)为源点建立最短路树,这样跨越(mid)的点对之间的最短路一定会经过(mid),因此两点之间的最短路径就可以描述成最短路树上的两段到根路径。对每棵最短路树处理(dfs)序,用树状数组维护权值修改即可。
[Wannafly挑战赛4F]线路规划
类似SCOI2016萌萌哒一题,并查集(f_{i,j})表示从(i)点开始往上(2^j)个祖先的集合,然后依然按照(Kruskal)的理论从小往大加边。卡常warming。
[UOJ236][IOI2016]railroad
相当于是要构造一条起点在(0)终点在(inf)的欧拉路,为了方便从(inf)向(0)连一条边转为求欧拉回路。在保证每个点的度数为偶数的前提下用最小的代价使图连通即可。
[CSAcademy]Divisible Matching
先随便找到一个存在(k)次单位根的质数(p),对矩阵中的每个非(-1)位随机一个权值(b_{i,j}),然后每次令(a_{i,j}=b_{i,j imes }(omega^t)^{e_{i,j}})求一次行列式,答案相加。若不存在一个合法排列,则答案一定为(0),否则答案以极大概率不为(0)。
[CSAcademy]Xor Transform
考虑((i,j))位置最终对((0,0))的贡献,显然被计算了(inom{T}{i}inom{T}{j})次,要使这个数在模(2)意义下为(1)则说明(i|j)是(T)的子集。高维后缀和即可。
[CSAcademy]Sort All
一个常见的套路是,右端点从左往右扫,维护所有左端点的答案,这里只要维护所有的左端点的答案之和。
先考虑所有数互不相同的情况。考虑新增一个(r),首先(r)自身会是答案加上若干个(r),即每个区间内比(r)小的数的数量。同时(r)的加入也会使比(r)大的数的权值增加,讨论一下即可。
如有相同的数其实也很简单,只要对每种数只保留最后一次出现即可。
实现时需要用一个二位数据结构维护,两维分别是下标与权值。需要维护的量有(sum 1,sum i,sum a_i,sum a_ii)。
[CF908G]New Year and Original Order
其实只要考虑在每一个数中大于等于数字(x)的数字出现了多少次就可以算出其贡献了。简单(dp)一下即可。
[AGC30F]Permutation and Minimum
令((2i-1,2i))为一对,显然((x,y))对对答案没有任何影响可以忽视。现在我们已经得到了若干对((-1,x)),若干对((-1,-1)),在这里((-1,x))的本质是限制了两个不同对中的(x)不能组成一对。考虑从大往小确定位置以处理取(min)。设(f_{i,j,k})表示确定前(i)大数的位置,剩余有(j)个在输入中出现过的数尚未匹配,(k)个在输入中未出现的数尚未匹配,转移只要考虑当前的第(i-1)大数是自己新开一组匹配还是与之前一个待匹配位置匹配,其中在“输出中未出现的数匹配输出中出现过的数”时方案数要乘上(j)。最终答案要乘上((-1,-1))的数量的阶乘。
[ARC073F]Many Moves
有一个十分显然的(O(nq))的(dp)做法。
直接用线段树维护这个(dp)就行了。主要支持的操作有:全局加,以及用整棵线段树去更新一个单点。需要维护(f_i,f_i-i,f_i+i)的最小值。
[AGC013D]Piling Up
相当于是求从(y=0)出发,每步可以走((1,1))或是((1,-1))最终到达(y=2m)的不同路线数,这里定义路线上下平移算作相同。为了解决算重的问题可以强制路线经过(x=0)。
[TopCoder11213]AppleTrees
假设任两棵树之间的距离都是(max(r_i,r_j)),之后再把剩下的距离用隔板法分配进去即可。所有树按照(r_i)从小往大加入,这样两树之间的距离就有后加入的树确定,(f_{i,j,k})表示前(i)棵树,排列共分成(j)段,总距离为(k)的方案数,转移显然。
[Luogu3297][SDOI2013]逃考
对每个亲戚求出其掌控范围,然后求个最短路即可。可以直接半平面交实现做到(O(n^2log n))。
[UOJ27][IOI2014]Gondola
Case1:判断所有(le n)的数的权值减下标(模(n)意义下)是否都相等,以及判断是否有重复元素。
Case2:多余的替换全部丢到最大的那个位置上即可。
Case3:一个缆车的替换方案至多只有(n)种,直接找出计算贡献的区间然后快速幂即可。
[UOJ28][IOI2014]Friend
可以看做变种的树上最大独立集问题。依然对每个点记(f_x,g_x)表示(x)选或不选的最优答案(这其中的另一层含义是,(f_x)表示(x)的儿子一个都没有选,(g_x)表示可能选择了(x)的儿子)。
普通连边方式的转移为(f_xgets f_x+g_y, g_x gets g_x+min(f_y,g_y))。
对于所有兄弟连边的连边方式,转移为(f_xgets max(f_x+max(f_y,g_y),g_x+f_y),g_xgets g_x+g_y)。
对于第三种连边方式,转移为(f_xgetsmax(f_x+g_y,g_x+f_y),g_xgets g_x+g_y)。
[UOJ29][IOI2014]Holiday
考虑确定最终访问到的区间([l,r](lle s le r)),收益即为除去走路用的(r-l+min(r-s,s-l))步后,剩下的步数在区间([l,r])内取前若干大。
一个小结论是,每个(l)对应的最优的(r)是单调的,于是分治+主席树求前(k)大(O(nlog^2n))美滋滋。
[UOJ426][集训队作业2018]石像
显然是个二合一
其中(G(d)=sum_{i|d}sigma_0(i^3)^3mu(frac di),F(m)=sum_{a_1=1}^msum_{a_2=1}^m...sum_{a_n=1}^mprod_{j=1}^k[a_{x_j}le a_{y_j}])。
前半部分是个积性函数的前缀和,直接(min\_25)即可。后半部分,可以发现是一个不超过(n)次多项式,插值即可。
手玩可以发现(G(p^c)=81c^2-27c+9)。
[UOJ229][IOI2015]Boxes
贪心,一次一定只选一段连续的区间。枚举第一段区间选多长,再暴力算后面的答案,复杂度(O(k imes frac nk)=O(n))。
[UOJ231][IOI2015]Teams
把区间([a_i,b_i])看做一个二维平面上的点。每次选点都会在当前可选点集中选择一些纵坐标最小的点。
问题在于如何维护单次操作中已选择的点集。会发现已选点集会在平面上构成的矩形的高度是单调不降的(否则一定不优),所以就用单调栈维护这个高度就行了。
[UOJ232][IOI2015]Horses
数字很大转自然对数后进行运算即可。
[UOJ233][IOI2015]Sorting
答案具有可二分性,而且两个人的操作是可以独立的,直接构造第一个人的操作即可。所以说这其实是一道代码实现题。
[Luogu4587][FJOI2016]神秘数
设区间中前(k)小的数之和为(sum),且第(k+1)小的数超过了(sum+1),则(sum+1)这个数就不可能被构造出来了。
由此可以不断将值域扩大,当发现扩大值域后权值没有增加则说明已经找到了答案。
[CF833D]Red-Black Cobweb
将(2min(a,b)ge max(a,b))的限制拆成(2age b)与(2bge a)。合并路径时限制要求变成了(2(a_1+a_2)ge b_1+b_2,2(b_1+b_2)ge a_1+a_2),随便划下式子就是(2a_1-b_1ge-(2a_2-b_2),2b_1-a_1ge -(2b_2-a_2))。看似一个二维偏序的模型但实际上这两者中至少有一者是会被满足的,所以只需要分别减去违反两个条件的贡献就行了。
[CF833E]Caramel Clouds
先不管(q)组询问,直接处理出(kin[0,+infty))的答案。扫描线从左向右扫,维护(f_i)表示第(i)朵云单独覆盖的长度,(g_i)表示第(i)朵云与其他的一朵云覆盖得到的最大长度。当扫到一段区间不被任何云覆盖时,可以直接加入答案。当一段区间只被一朵云覆盖时,可以更新这朵云的(f)值,用满足(c_i+c_jle C)的云(按云的权值排序后对应一段前缀)去更新这朵云的(g)值,同时更新答案。当一段区间被两朵云覆盖时,可以直接开std::map
记录两片云共同覆盖的部分的长度,更新两者的(g)值再更新答案即可。
[BZOJ2741]【FOTILE模拟赛】L
首先做前缀和后转成求区间内选两个数异或和最大。
分块预处理出(f_{i,j})表示从第(i)个块的块首到第(j)的位置这段区间里任选两个数异或的最大值,询问再暴力处理(l)所在的非整块。复杂度(O((n+m)sqrt n imes 30))
[CF1132G]Greedy Subsequences
令(pre_i)为(i)之前第一个大于等于(a_i)的数的位置,那么(i)的出现可以使([pre_i+1,i])中的每个数作为起始位置的答案(+1),扫一遍用个线段树维护一下即可。
[CodeChef - CNTDSETS]Counting D-sets
强制所有坐标都为非负整数且每一维都有至少一个(0)即可解决平移等价的问题,直径恰好为(d)可以转化为至多为(d)减去至多为(d-1),即要求每个点每一维坐标不超过(d)。
容斥,枚举一些维不出现(0),剩下的维任意,答案是(sum_{i=0}^ninom ni(-1)^i2^{d^i(d+1)^{n-i}})。
[CodeChef - CNTL]Counting is life
当(n)与(k)同奇偶时,第一问答案显然是所有数的异或和,即(2^k-1),因而就要求每个数都出现了奇数次,答案为([x^n](frac{e^x-e^{-x}}{2})^k=sum_{i=0}^kinom ki(-1)^i[x^n]e^{(k-2i)x}=sum_{i=0}^kinom ki(-1)^i(k-2i)^n)。
当(n)与(k)异奇偶时第一问答案是(2^k-2),要求(k-1)个数出现奇数次而(1)出现偶数次,与上式类似,答案是(sum_{i=0}^{k-1}inom{k-1}{i}(-1)^i((k-2i)^n+(k-2i-2)^n))。
[LOJ6392][THUPC2018]密码学第三次小作业
已知(a=m^cmod n,b=m^d mod n),给出(a,b,c,d,n),保证((c,d)=(n,m)=1)求(m)?
(m=m^1=m^{cx+dy}),用扩展欧几里得求出一组合法的(x,y)后(m=a^xb^y)。
[UOJ424][集训队作业2018]count
可以写出一个(O(n^2m))的(dp)式:(f_{i,j}=sum_{k=1}^jf_{i-1,k-1} imes f_{i,j-k}),特别的,(f_{i,0}=1)。
令(F_i(x)=sum_{jge 0}f_{i,j}x^j),可以发现(F_i(x)=F_{i-1}(x)F_i(x)x+1),解出来(F_i(x)=frac{1}{1-F_{i-1}(x)x})。
考虑设(F_i(x)=frac{A_i(x)}{B_i(x)}),则(F_{i+1}(x)=frac{1}{1-frac{A_i(x)}{B_i(x)}x}=frac{B_i(x)}{B_i(x)-A_i(x)x}),即(A_{i+1}(x)=B_i,B_{i+1}(x)=B_i(x)-A_i(x)x)。
矩乘转移即可。由于矩阵元素是多项式,可以考虑将单位根作为点值代入再(idft)即可。
[BZOJ3601]一个人的数论
后面的(sum_{i=1}^{frac nj}i^d)是一个关于(frac nj)的(d+1)次多项式,设其为(sum_{k=0}^{d+1}a_kx^k),于是
后一部分是积性函数可以对每个质因子分别求解后乘起来。求(a_k)直接拉格朗日插值即可,复杂度(O(wd+d^2))。
[BZOJ4671]异或图
容斥,枚举一个(n)点划分的方案,即将(n)个点划分成若干点集,强制要求不同点集之间没有边(点集内部不一定连通),计算方案数并乘上容斥系数即可。
方案数的计算即要求不同点集之间的边的取值是(0),可以只考虑这些边,用输入的图做一遍线性基,方案数就是(基的数量2^{s-mbox{基的数量}})。
容斥系数在这里不再是普通的(pm 1)。考虑设将(n)个点划分成(i)个不同点集时的容斥系数是(f_i),则需要满足(sum_{i=1}^megin {Bmatrix} m \ iend {Bmatrix}f_i=[m=1]),其中(m)表示的是真实的连通块数量。可以直接解方程求出(f_i),也可以根据斯特林反演得到(f_m=sum_{i=1}^m(-1)^{m-i}egin{bmatrix}m\iend{bmatrix}[i=1]=(-1)^{m-1}(m-1)!)。