2019 ICPC亚洲区域赛银川赛区题解

E题题解

题意

给定一个 n n n 个节点的有根树,每个节点有一个权值 A i A_i Ai。定义一个集合的价值为: V a l u e ( S ) = ∑ x ∈ S ∑ y ∈ S ( A x ⊕ A y ) 2 Value(S)=\sum_{x\in S}\sum_{y \in S}{(A_x \oplus A_y)^2} Value(S)=xSyS(AxAy)2

求以每个节点 x x x 为根的子树中距离 x x x 不超过 k k k 的节点集合 V ( x , k ) V(x,k) V(x,k) 的价值。

k ≤ n ≤ 1 0 5 , 0 ≤ A i ≤ 1 0 9 k \leq n \leq 10^5,0 \leq A_i \leq 10^9 kn105,0Ai109

解法

考虑如何计算一个集合的价值,问题的难点在于求 ∑ ( a ⊕ b ) 2 \sum_{(a \oplus b)^2} (ab)2,设 a ⊕ b = x a \oplus b = x ab=x 并写出 x x x 的二进制表示 x = x 30 + x 29 + . . . + x 0 x = x_{30}+ x_{29} + ... + x_0 x=x30+x29+...+x0

x 2 = ( ∑ x i ) 2 = ∑ ∑ x i x j x^2=(\sum{x_i})^2=\sum\sum{x_i x_j} x2=(xi)2=xixj,这提示我们对于每两位 ( i , j ) (i,j) (i,j) 计算出有多少对 ( a , b ) (a,b) (a,b) 满足 a ⊕ b a \oplus b ab 的第 i i i 位和第 j j j 位均为 1 1 1 即可。

这一步的计算可以通过维护有多少个数满足第 i i i 位为 x i x_i xi ,第 j j j 位为 x j x_j xj,设为 s ( x i , x j ) s(x_i,x_j) s(xi,xj)。然后用 s ( 0 , 0 ) s ( 1 , 1 ) + s ( 0 , 1 ) s ( 1 , 0 ) s(0,0)s(1,1)+s(0,1)s(1,0) s(0,0)s(1,1)+s(0,1)s(1,0) 就能计算出对答案的贡献。

现在我们将这种做法推广到原问题,使用长链剖分维护每个深度的信息,前缀和计算即可。

设权值的字长为 w w w ,则总时间复杂度为 O ( n w 2 ) O(nw^2) O(nw2),空间复杂度为 O ( n ) O(n) O(n)

A题题解

题意:

给出 n ( n ≤ 100000 ) n(n\leq100000) n(n100000)个物品,每个物品有一个 n a m e name name属性和一个 c o l o r color color属性和一个 p o w e r power power,再给出 5 5 5 n a m e name name值和 1 1 1 c o l o r color color值。选出 5 5 5个物品,定义 b o n u s bonus bonus初始为 1 1 1,每有一个物品的 n a m e name name在给出的 n a m e name name中则 b o n u s + = 10 % bonus+=10\% bonus+=10%,每有一个物品的 c o l o r color color为给出的 c o l o r color color b o n u s + = 20 % bonus+=20\% bonus+=20%,定义 得 分 = 5 个 物 品 p o w e r 的 和 × b o n u s 得分=5个物品power的和\times bonus =5power×bonus,求选出的 5 5 5个物品得分最高为多少

解法

所有的牌都可以分为4类
0:名字没有加成,颜色没有加成
1:名字有加成,颜色没有加成
2:名字没有加成,颜色有加成
3:名字有加成,颜色有加成

把类别相同的都放在同一个数组中
然后把每个数组都按照power从大到小排序。
题目要求每个名字只能被选取一次,因此对每个数组去重,每个名字只保留power最高的。
设最后的四个数组为V[0],V[1],V[2],V[3]
然后进行搜索,深度为5
每次从V[0],V[1],V[2],V[3]中选取一张牌。
每次选取时都优先选power最高的,如果名字重复就跳过
dfs部分大概长这样

void dfs(int deep,int nname,int ncolor,int power,int i0,int i1,int i2,int i3,set<string>name_set){
	if(deep == 0){
		update(ans,power*(1.0+nname*0.1+ncolor*0.2));
		return;
	}
	//V[0]部分
	...//跳过名字相同的,因为name_set最多5个元素,因此复杂度很低
	name_set.insert(now_name);
	dfs(deep-1,nname,ncolor,power+now_power,i0+1,i1,i2,i3,name_set);
	name_set.erase(now_name);
	//V[1]部分
	...//同样跳过
	name_set.insert(now_name);
	dfs(deep-1,nname+1,ncolor,power+now_power,i0,i1+1,i2,i3,name_set);
	name_set.erase(now_name);
	//后面都差不多
}

时间复杂度:
排序 O ( n l o g n ) O(nlogn) O(nlogn)
搜索 O ( 1 ) O(1) O(1)
因此总复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

Problem N

输出 1 1 2 3 5

Problem B

一个 n × m n\times m n×m 矩阵, n , m ≥ 2 n,m\geq 2 n,m2 ,初始全0,每次可以行+1或列+1。现在某一个数丢失,求它是多少。

注意到 a x y + a z w = a x w + a z y a_{xy}+a_{zw}=a_{xw}+a_{zy} axy+azw=axw+azy 即可。

Problem G

维护一个数组,区间乘一个 2 ≤ x ≤ 10 2\leq x\leq 10 2x10 的数字,区间查询 pot ⁡ ( x ) \operatorname{pot}(x) pot(x) 的最大值,其中
pot ⁡ ( x ) : = max ⁡ p   p r i m e ,   p c ∣ x c . \operatorname{pot}(x):=\max_{p\ \mathrm{prime},\ p^c|x}c. pot(x):=p prime, pcxmaxc.
做法:对 2 , 3 , 5 , 7 2,3,5,7 2,3,5,7 分别维护一颗线段树,区间加、区间取 max ⁡ \max max 即可。

Problem F


∑ a = 2 n a ∑ b = a n ⌊ log ⁡ a b ⌋ ⌈ log ⁡ b a ⌉ ,   n ≤ 1 0 12 . \sum_{a=2}^n a\sum_{b=a}^n{\left\lfloor\log_a b\right\rfloor\left\lceil\log_b a\right\rceil},\,n\leq10^{12}. a=2nab=anlogablogba,n1012.
注意到 b ≥ a b\geq a ba ⌈ log ⁡ b a ⌉ = 1 \lceil \log_b a\rceil=1 logba=1 a ≤ n a \leq \sqrt n an 可枚举内层爆算, a > n a>\sqrt n a>n 时内层的乘积就是 1 1 1 ,因此内层 ∑ = n − a + 1 \sum=n-a+1 =na+1

Problem I

将一个 x x x 进制下的数字 k k k 转换到 y y y 进制下。 k ≤ x 120 k\leq x^{120} kx120

简单 Python 作业题。注意特判 0。

Problem K

给定两个 n × m n\times m n×m 矩阵,每个里面元素都是 1 … n × m 1\dots n\times m 1n×m 且两两不同。求最大公共(连续)子矩阵大小。

做法:因为是排列所以可以找到每个元素在哪里。 O ( n m ) O(nm) O(nm) 可以求出每个 a i j a_{ij} aij b b b 里面向上、左、右走 1 × k 1\times k 1×k k × 1 k\times 1 k×1 能走多远,分别设为 U ( i , j ) ,   L ( i , j ) ,   R ( i , j ) U(i,j),\,L(i,j),\,R(i,j) U(i,j),L(i,j),R(i,j)。剩下的事情是一个悬线法:

  • 对于最大的方案,一定存在某一列,使得这一列是不能向上拓展的(否则每列都可以向上拓展,与最大性相矛盾),我们称这一列是瓶颈。
  • 对于每一个 ( i , j ) (i,j) (i,j) ,我们可以 DP 出,下边界是第 i i i 行且瓶颈是第 j j j 列时的最大左右扩展距离。详见OI Wiki上的悬线法条目。这里的特殊点是要对 L ( i , j ) ,   R ( i , j ) L(i,j),\,R(i,j) L(i,j),R(i,j) min ⁡ \min min

就做完了。

Problem D

我们定义一个序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an ( n , m , d ) (n,m,d) (n,m,d)-好的,当且仅当:

  • ∀ 1 ≤ i ≤ n ,   1 ≤ a i ≤ m \forall 1\leq i\leq n,\,1\leq a_i\leq m 1in,1aim ,并且
  • gcd ⁡ ( a 1 , ⋯   , a n ) = d \gcd(a_1,\cdots,a_n)=d gcd(a1,,an)=d

给定 n , m , d , k n,m,d,k n,m,d,k ,求所有 ( n , m , d ) (n,m,d) (n,m,d)-好的序列的“所有元素的积的 k k k 次幂”的和,对某个合数取模。输入的 n ≤ 1 0 100000 ,   m ≤ 100000 ,   k ≤ 1 0 9 n\leq 10^{100000},\,m\leq 100000,\,k\leq 10^9 n10100000,m100000,k109

Solution

下述过程中, n n n 只出现在指数位置上,所以我们只需要取 n ← n   m o d   φ ( m o d ) n\leftarrow n\bmod \varphi(mod) nnmodφ(mod) ,这样的读入是轻易的。给定 n , k n,k n,k ,我们设 f ( x ) f(x) f(x) 是所有 ( n , x , 1 ) (n,x,1) (n,x,1)-好的序列的“所有元素的积的 k k k 次幂”的和。则答案是 d k n f ( ⌊ m d ⌋ ) d^{kn} f\left(\left\lfloor\frac{m}{d}\right\rfloor\right) dknf(dm) 。注意到我们有容斥
f ( x ) = ( T x ) n − ∑ j = 2 x j k n f ( ⌊ x j ⌋ ) , f(x)=(T_x)^n-\sum_{j=2}^x j^{kn}f\left(\left\lfloor\frac{x}{j}\right\rfloor\right), f(x)=(Tx)nj=2xjknf(jx),
其中 T x = ∑ i = 1 x i k T_x=\sum_{i=1}^x i^k Tx=i=1xik 。第一项是不考虑 gcd ⁡ \gcd gcd 限制的总和,后面的是 gcd ⁡ \gcd gcd 容斥。记忆化搜索,所有的状态都形如 f ( ⌊ m j ⌋ ) f\left(\left\lfloor\frac{m}{j}\right\rfloor\right) f(jm) for some j j j ,故状态只有 O ( m ) O\left(\sqrt m\right) O(m ) 个。

考虑转移,这是简单的数论分块:若 j ≤ x j\leq \sqrt x jx 直接算;若 j > x j>\sqrt x j>x ,枚举 p = ⌊ x j ⌋ < x p=\left\lfloor\frac{x}{j}\right\rfloor< \sqrt x p=jx<x ,考虑满足 ⌊ x j ⌋ = p \left\lfloor\frac{x}{j}\right\rfloor =p jx=p j j j 是一个区间 [ ⌊ x / ( p + 1 ) ⌋ + 1 , ⌊ x / p ⌋ ] [\lfloor x/(p+1)\rfloor+1,\lfloor x/p\rfloor] [x/(p+1)+1,x/p] ,对这个区间计算贡献,只要预处理 j k n j^{kn} jkn 的前缀和然后减一减就可以了。因此转移复杂度 O ( m ) O(\sqrt m) O(m ) ,故DP的总复杂度 O ( m ) O(m) O(m)

再来看预处理的复杂度。预处理要求 i k i^k ik 的前缀和与 i k n i^{kn} ikn 的前缀和。先求出他们俩本身:这两个东西都是完全积性函数,可以 O ( m log ⁡ m log ⁡ m o d ) O\left(\frac{m}{\log{m}}\log mod\right) O(logmmlogmod) 线性筛,因此可以线性求出;然后前缀和也是线性的。因此总复杂度是 O ( m ) O(m) O(m) 的。

Problem J

给你一张每条边至多在一个简单环上的无向图,边有非负边权。求:从1号节点出发,经过每条边至少一次,结束在任意位置的最短方案。要求复杂度线性。

Solution

首先,一些基本的常识和术语可见vfk的玩转仙人掌讲义。需要前置完成构建仙人掌的 Block Forest 结构(又名“仙人掌的圆方树”、点双树,就是vfk讲义里面没有提到名字的树结构,把环上的点作为环儿子,把环的最高顶点作为环父亲)。额外地,需要维护环上边权的前缀和。这些都可以朴素完成。

我们定义 F x F_x Fx 为从 x x x 的父亲进入 x x x 的子仙人掌,遍历所有边至少一遍,然后回到 x x x 的父亲的最小花费;定义 G x G_x Gx 为从 x x x 的父亲进入 x x x 的子仙人掌,遍历所有边至少一次,最后停止在任意节点的最小花费。注意如果 x x x 不是环, F x , G x F_x,G_x Fx,Gx 中就会包含 ( f a t h e r x , x ) (\mathrm{father}_x,x) (fatherx,x) 的边权(两次或一次,resp.)。我们可以给根定义一个零花费的父向边以避免一些无谓的平凡情况。以下的 DP 过程几乎是平凡的,但在此详述,只为搞清一下细节。

x x x 是结点(“圆点”),那么 F x = 2 w ( ( f a t h e r x , x ) ) + ∑ y ∈ s o n s x F y F_x=2w((\mathrm{father}_x,x))+\sum\limits_{y\in\mathrm{sons}_x} F_y Fx=2w((fatherx,x))+ysonsxFy ,其中 e ↦ w ( e ) e\mapsto w(e) ew(e) 代表边权;若 x x x 是环(“方点”),可以发现最优方案是环边只走一遍、所有其他孩子直接进去再回来,因此 F x = ∑ e ∈ e d g e s x w ( e ) + ∑ y ∈ s o n s x F y F_x=\sum\limits_{e\in \mathrm{edges}_x} w(e)+\sum\limits_{y\in\mathrm{sons}_x} F_y Fx=eedgesxw(e)+ysonsxFy

x x x 是结点,考虑 G x G_x Gx ,进入 x x x 之后,最后一定会落在某个子仙人掌中,因此枚举最后终结的地方在哪个孩子的子树中,可以得到
G x = w ( ( f a t h e r x , x ) ) + min ⁡ y ∈ s o n s x ( G y + ∑ z ∈ s o n s x ,   z ≠ y F y ) = F x − w ( ( f a t h e r x , x ) ) + min ⁡ y ∈ s o n s x ( G y − F y ) , \begin{aligned}G_x &=w((\mathrm{father}_x,x))+\min\limits_{y\in\mathrm{sons}_x} \left(G_y+\sum\limits_{z\in\mathrm{sons}_x,\,z\neq y} F_y\right)\\&=F_x-w((\mathrm{father}_x,x))+\min\limits_{y\in\mathrm{sons}_x}\left(G_y-F_y\right),\end{aligned} Gx=w((fatherx,x))+ysonsxminGy+zsonsx,z=yFy=Fxw((fatherx,x))+ysonsxmin(GyFy),
x x x 是环,可以发现总会落在某一个节点的子仙人掌中,照样枚举是哪个节点。假设它是 y y y 。由于环上的每条边都要经过一遍,我们从顶点开始、先走一圈、回到顶点,然后从顶点下到 y y y
G x = ∑ e ∈ e d g e s x w ( e ) + min ⁡ y ∈ s o n s x ( d i s ( x , y ) + G y + ∑ z ∈ s o n s x ,   z ≠ y F y ) = F x + min ⁡ ( 0 , min ⁡ y ∈ s o n s x ( d i s ( x , y ) + G y − F y ) ) , \begin{aligned}G_x &=\sum\limits_{e\in \mathrm{edges}_x} w(e)+\min\limits_{y\in\mathrm{sons}_x} \left(\mathrm{dis}(x,y)+G_y+\sum\limits_{z\in\mathrm{sons}_x,\,z\neq y} F_y\right)\\&=F_x+\min\left(0,\min\limits_{y\in\mathrm{sons}_x}\left(\mathrm{dis}(x,y)+G_y-F_y\right)\right),\end{aligned} Gx=eedgesxw(e)+ysonsxmindis(x,y)+Gy+zsonsx,z=yFy=Fx+min(0,ysonsxmin(dis(x,y)+GyFy)),
其中 d i s \mathrm{dis} dis 由于在同一个环上,可以把环的两侧取 min ⁡ \min min ,这里要用到上述的“环上的边权前缀和”。

答案就是 G 1 G_1 G1 了。

你可能感兴趣的:(比赛题解)