多校联考 Day 7 总结

总结


\qquad 一次绝妙的阿克机会,可惜没把握住……

时间安排


8 : 00 ∼ 8 : 10 \qquad 8:00\sim 8:10 8:008:10 看题。看了 T 1 T1 T1 发现好像以前写过,直接秒了。

8 : 10 ∼ 9 : 30 \qquad 8:10\sim 9:30 8:109:30 T 2 T2 T2。发现 T 2 T2 T2 也挺水,但是没有 T 1 T1 T1 那么水,就先通读了题面。发现今天的题很平和,打算一道一道来。 T 2 T2 T2 一眼贪心,但是贪心策略想的有一点复杂。赛时考虑到这一策略可以用线段树实现,时间复杂度大约 O ( 2 m   l o g   n ) O(2m\,log\,n) O(2mlogn),有点卡但是应该可过,就写了,调了一小会后过了大样例,但是跑了 5 s 5s 5s,想着去自定义测试上测测,但是发现时限 10 s 10s 10s,而且自定义测试放不进大样例,就选择了直接交。

9 : 30 ∼ 10 : 30 \qquad 9:30\sim 10:30 9:3010:30 T 3 T3 T3,第一眼以为是个大摩你,不是很想写,就看了 T 4 T4 T4。这时注意到 c z l czl czl 已经交了 T 4 T4 T4,想着可能不是很难(毕竟交的很快),但是看了两眼感觉还是无思路,就回头看了 T 3 T3 T3。看着什么复数乘法,感觉很难,慢慢推……突然发现题目中的 a + b i = ( q r + q i × i ) ( − 1 + i ) + r a+b_i=(q_r+q_i\times i)(-1 + i)+r a+bi=(qr+qi×i)(1+i)+r,想着展开式子,发现可以直接解 q r , q i q_r, q_i qr,qi,于是处理了一下本题唯一的难点:读入后就过了。

10 : 30 ∼ 12 : 00 \qquad 10:30\sim 12:00 10:3012:00 想着还有一个半小时,但是只剩一个 T 4 T4 T4 了,那今天不是随便阿克? 推了一小会式子发现很难在 O ( n   l o g   n ) O(n\,log\,n) O(nlogn) 的时间复杂度内处理出来,考虑先打暴力。但是发现这个式子对于 O ( n 2 ) O(n^2) O(n2) 的复杂度好像也不是很好实现,就想着能不能用其他方式来统计。发现不太会,但是此时发现 T 2 T2 T2 时限缩短为 3 s 3s 3s,于是搬出来了 i o b u f f iobuff iobuff,卡了个小常,在本地跑大样例 4 s 4s 4s 的情况下安慰自己评测及跑得快就交了。然后继续推 T 4 T4 T4,猜测是 d p dp dp,但是不会写,就寄了,直到结束。


考试结果


100 + 30 + 100 + 0 = 230 p t s ,    R a n k : + ∞ \qquad 100+30+100+0=230pts,\;Rank:+\infty 100+30+100+0=230pts,Rank:+ T 2 T2 T2 线段树果然是跑不过去。


考试总结


\qquad 菜啊,还得多练……

\qquad T 2 T2 T2 的贪心策略就是正解,但是因为没往下深想所以没想到更简洁的实现方法。而且, T 2 T2 T2 以前作为模拟赛的题考过,但是我没想起来! 以前总结下来的经验还是要经常复习。

\qquad T 4 T4 T4 连第一步都没想到,一直在往 2 d 2^d 2d 上想,没有往子树上想,导致最基础的 d p dp dp 也没想到,很崩。以后遇到一道无思路的题,试思路的时候不能堵到一条路上,要迭代加深,不能一味 d f s dfs dfs

题解

T1

T1

\qquad k ≤ 1 0 6 k\leq 10^6 k106 显然可以直接枚举倍数。

\qquad k ≤ 1 0 12 k\leq 10^{12} k1012 可以考虑将 k k k 分解质因数, k = p 1 c 1 p 2 c 2 … k=p_1^{c_1}p_2^{c_2}\dots k=p1c1p2c2,那么最小的 n = p 1 ⌈ c 1 2 ⌉ p 2 ⌈ c 2 2 ⌉ … n=p_1^{\left \lceil \frac{c_1}{2} \right \rceil }p_2^{\left \lceil \frac{c_2}{2} \right \rceil }\dots n=p12c1p22c2。最后判断 n n n 是否能整除 k k k 即可。

T2

T2

\qquad 考虑一条边被删除当且仅当这条边两端点之一被删除。假设这条边连接 x , y x,y x,y,那么这条边带来的贡献要么是删 x x x 带来 v y v_y vy,要么是删 y y y 带来 v x v_x vx。也就是说, ∑ i = 1 m m i n ( v x i , v y i ) \sum_{i=1}^{m}min(v_{x_i}, v_{y_i}) i=1mmin(vxi,vyi) 一定是答案的一个下界,答案不可能比它小。

\qquad 现在,我们考虑能否构造出一个删除方案使得答案等于它。我们考虑给每一条无向边赋方向:让点权大的点指向点权小的点。若两点点权相同,可以考虑让编号大的点指向编号小的点。这样,我们构造出的有向图一定是一个 D A G DAG DAG。跑出来的拓扑序就是我们删点的顺序。所以,我们证明了一定可以构造出一个删点方案,使得 a n s = ∑ i = 1 m m i n ( v x i , v y i ) ans=\sum_{i=1}^{m}min(v_{x_i}, v_{y_i}) ans=i=1mmin(vxi,vyi)。在读入的时候加一下即可。

T3

T3

\qquad 乍一看,本题好像是个大摩你。但是,发现了 a + b i = ( q r + q i × i ) ( − 1 + i ) + r a+bi=(q_r+q_i\times i)(-1+i)+r a+bi=(qr+qi×i)(1+i)+r 这一式子后,一切的问题就迎刃而解。我们把式子拆开:

a + b i = ( q r + q i × i ) ( − 1 + i ) + r a+bi=(q_r+q_i\times i)(-1+i)+r a+bi=(qr+qi×i)(1+i)+r
a + b i = − q r − q i × i + q r × i − q i + r a+bi=-q_r-q_i\times i+q_r\times i-q_i+r a+bi=qrqi×i+qr×iqi+r
a + b i = ( r − q r − q i ) + ( q r − q i ) × i a+bi=(r-q_r-q_i)+(q_r-q_i)\times i a+bi=(rqrqi)+(qrqi)×i
a = r − q r − q i , b = q r − q i a=r-q_r-q_i,b=q_r-q_i a=rqrqi,b=qrqi
q r = b − ( a + b − r ) 2 , q i = − ( a + b − r ) 2 q_r=b - \frac{(a + b - r)}{2}, qi = -\frac{(a + b - r)}{2} qr=b2(a+br),qi=2(a+br)

\qquad 所以每次让 q r , q i q_r,q_i qr,qi 成为新的 a , b a,b a,b,递归求解即可。

\qquad 本题唯一的码量在于处理读入时的实部,虚部。

T4

T4

\qquad 首先,想想朴素版怎么写:枚举 x , y x,y x,y 子树中的节点,两两配对成一条路径。写成式子就是: ∑ i = 1 s z e x ∑ j = 1 s z e y 2 d i s ( x , y ) + d i s ( i , x ) + d i s ( j , y ) \sum_{i=1}^{sze_x}\sum_{j=1}^{sze_y}2^{dis(x,y)+dis(i,x)+dis(j,y)} i=1szexj=1szey2dis(x,y)+dis(i,x)+dis(j,y),考虑化简式子:

∑ i = 1 s z e x ∑ j = 1 s z e y 2 d i s ( x , y ) + d i s ( i , x ) + d i s ( j , y ) \sum_{i=1}^{sze_x}\sum_{j=1}^{sze_y}2^{dis(x,y)+dis(i,x)+dis(j,y)} i=1szexj=1szey2dis(x,y)+dis(i,x)+dis(j,y)
= ∑ i = 1 s z e x ∑ j = 1 s z e y 2 d i s ( x , y ) × 2 d i s ( i , x ) × 2 d i s ( j , y ) \sum_{i=1}^{sze_x}\sum_{j=1}^{sze_y}2^{dis(x,y)}\times 2^{dis(i,x)}\times 2^{dis(j,y)} i=1szexj=1szey2dis(x,y)×2dis(i,x)×2dis(j,y)
= 2 d i s ( x , y ) ∑ i = 1 s z e x ∑ j = 1 s z e y 2 d i s ( i , x ) × 2 d i s ( j , y ) 2^{dis(x,y)}\sum_{i=1}^{sze_x}\sum_{j=1}^{sze_y}2^{dis(i,x)}\times 2^{dis(j,y)} 2dis(x,y)i=1szexj=1szey2dis(i,x)×2dis(j,y)
= 2 d i s ( x , y ) ∑ i = 1 s z e x 2 d i s ( i , x ) × ∑ j = 1 s z e y 2 d i s ( j , y ) 2^{dis(x,y)}\sum_{i=1}^{sze_x}2^{dis(i,x)}\times \sum_{j=1}^{sze_y}2^{dis(j,y)} 2dis(x,y)i=1szex2dis(i,x)×j=1szey2dis(j,y)

\qquad 化简到这一步,我们不妨设 f x = ∑ i = 1 s z e x 2 d i s ( i , x ) f_x=\sum_{i=1}^{sze_x}2^{dis(i,x)} fx=i=1szex2dis(i,x),那么答案就是 f x × f y × 2 d i s ( x , y ) f_x\times f_y\times 2^{dis(x,y)} fx×fy×2dis(x,y) f f f 数组显然可以直接树形 d p dp dp 求。但是,我们发现:当 l c a ( x , y ) = x / y lca(x,y)=x/y lca(x,y)=x/y 时,这一式子是不成立的,如图:
特殊情况
\qquad x , y x,y x,y 是图中的 2 , 3 2,3 2,3 节点,那么 f 2 f_2 f2 代表的就是青色框中的点到 2 2 2 的距离,但是我们需要的是紫色框中的点到 2 2 2 的距离,即:以 2 2 2 为根的树去除以 3 3 3 为根的子树的点到 2 2 2 的距离。显然可以直接换根 d p dp dp 搞。设 g x g_x gx 表示: x x x 的父亲不走 x x x 这一棵子树能走到的点 x x x 的距离和,那么 g x = g f a x × 2 + f b r o × 4 g_x=g_{fa_x}\times 2+f_{bro}\times4 gx=gfax×2+fbro×4。以上图为例,答案便为 f 3 × g 3 × 2 d i s ( 3 , 3 ) f_3\times g_3\times 2^{dis(3,3)} f3×g3×2dis(3,3)。这一例子不太好,我们拿 1 , 3 1,3 1,3 举例,那么答案为 f 3 × g 2 × 2 d i s ( 2 , 3 ) f_3\times g_2\times 2^{dis(2,3)} f3×g2×2dis(2,3)。本题就解决了。

\qquad 核心代码:

void dfs(int x, int fa) {//求f
	fat[x][0] = fa, dep[x] = dep[fa] + 1, f[x] = 1;
	for(int i = 1; i <= 20; i ++) fat[x][i] = fat[fat[x][i - 1]][i - 1];
	for(int i = head[x]; i; i = edge[i].lst) {
		int v = edge[i].to;
		if(v == fa) continue;
		dfs(v, x);
		f[x] = (f[x] + (2LL * f[v]) % mod) % mod;
	}
}

void dfs1(int x, int fa, int val) {//求g
	g[x] = val;
	int sum = (2LL * g[x]) % mod;
	for(int i = head[x]; i; i = edge[i].lst) {
		int v = edge[i].to;
		if(v == fa) continue;
		sum = (sum + (4LL * f[v]) % mod) % mod;
	}
	for(int i = head[x]; i; i = edge[i].lst) {
		int v = edge[i].to;
		if(v == fa) continue;
		dfs1(v, x, (sum + 2LL - (4LL * f[v]) % mod + mod) % mod);//用全部的减当前子树的
	}
}

int Find(int x, int dis) {//从x开始往上跳dis的距离,最终会跳到哪个点
	for(int i = 20; i >= 0; i --)
		if((1 << i) <= dis) x = fat[x][i], dis -= (1 << i);
	return x;
}

...

if(l == x) {
	int tl = Find(y, dep[y] - dep[x] - 1);//找到lca与y这条链中,lca下方的第一个点  即上面1,3例子中的点2
	printf("%d\n", (1LL * (1LL * g[tl] * f[y]) % mod * qpow(2, dep[y] - dep[x] - 1)) % mod);
}
else printf("%d\n", (1LL * (1LL * f[x] * f[y]) % mod * qpow(2, dep[x] + dep[y] - 2 * dep[l])) % mod);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值