杭州学军中学信友队趣味网络邀请赛 总结
这次比赛我只考了 148 148 148分,虽然题目很难,但是还是考得不错,可以算是中山市小学生前 5 5 5名吧。这一次我就只做了前两题,后面的我就不讲了。
第一题
题目:
方法:
这道题其实很简单,主要的方法就是找规律,我也是在 4 4 4点半才找到规律的。我们多试几个例子,就可以找出。
对于子任务 1 1 1
我们可以直接用上面的样例来做,直接打表 。
对于子任务 2 2 2
可以在草稿纸上画一下,就可以得出了。
对于子任务 3 3 3~ 5 5 5
第一种方法——搜索:
可以用搜索来模拟这个图,应该只能拿到 50 50 50分左右。
第二种方法——数学(正解):
我们可以发现,当
n
n
n是偶数时:
当
n
n
n是奇数时:
其实他们都是按照这种方式的——就是缠绕法:
发现规律之后,我们直接模拟就可以了。
得分情况:
比赛时 100 100 100分。
第二题
题目:
方法:
这道题目比较简单理解,但是想拿满分不容易。
对于子任务 1 1 1
对于子任务 1 1 1,因为 n = 2 n=2 n=2,所以我们直接比较答案就行了。
对于子任务 2 2 2
对于子任务
2
2
2,我们可以打一个三重循环来过这道题,时间复杂度为
O
(
n
3
)
O(n^3)
O(n3)。
当然我也得了这么多分,但是我用的是
s
p
f
a
spfa
spfa,时间复杂度是
O
(
n
2
)
O(n^2)
O(n2),可能是因为
s
p
f
a
spfa
spfa的常数太大了,所以没有过子任务
3
3
3。
对于子任务 3 3 3
怎么求两个点的距离呢?
首先我们引入一个概念,
L
C
A
LCA
LCA,意思是最近公共祖先。
我们如何求两个点的
L
C
A
LCA
LCA呢?
求 L C A LCA LCA:
求 L C A LCA LCA的暴力方法
直接让两个点分别往上跳就行了。
倍增求 L C A LCA LCA
我们设
f
i
,
j
f_{i,j}
fi,j表示结点
i
i
i的
2
j
2^j
2j辈祖宗。
那么
f
i
,
0
=
f
a
f_{i,0}=fa
fi,0=fa
f
i
,
j
=
f
f
i
,
j
−
1
,
j
−
1
(
j
>
0
)
f_{i,j}=f_{f_{i,j-1},j-1}(j>0)
fi,j=ffi,j−1,j−1(j>0)
注:
f
a
fa
fa表示结点
i
i
i的父亲。
那么我们只用进行二进制拆分就可以算出
L
C
A
LCA
LCA了。
求深度:
我们求完
L
C
A
LCA
LCA之后,就要求深度(后面有用)。
我们设
d
e
p
x
dep_x
depx表示结点
x
x
x的深度。
则
d
e
p
x
=
d
e
p
f
a
+
1
dep_x=dep_{fa}+1
depx=depfa+1
计算距离:
我们求出了
L
C
A
LCA
LCA,就可以算出距离。
现在我们要求
x
x
x和
y
y
y的最短路径,那么
d
i
s
(
x
,
y
)
=
d
e
p
x
+
d
e
p
y
−
2
d
e
p
L
C
A
(
x
,
y
)
dis(x,y)=dep_x+dep_y-2dep_{LCA(x,y)}
dis(x,y)=depx+depy−2depLCA(x,y)
注:
d
i
s
(
x
,
y
)
dis(x,y)
dis(x,y)表示
x
x
x到
y
y
y的最短距离。
那么现在我们就可以用 O ( n 2 log n 2 ) O(n^2\log^2_n) O(n2logn2)的时间算出答案。
对于子任务 4 4 4(满分)
怎么才能的满分呢?
其实很简单。
我们重新看一下题目,题目可以变为:使
m
a
x
(
x
,
y
)
×
d
i
s
(
x
,
y
)
max(x,y)\times dis(x,y)
max(x,y)×dis(x,y)最大。
那么我们其实把
m
a
x
(
x
,
y
)
×
d
i
s
(
x
,
y
)
max(x,y)\times dis(x,y)
max(x,y)×dis(x,y)拆成
m
a
x
(
x
×
d
i
s
(
x
,
y
)
,
y
×
d
i
s
(
x
,
y
)
)
max(x\times dis(x,y),y\times dis(x,y))
max(x×dis(x,y),y×dis(x,y))。
怎么才能使
d
i
s
(
x
,
y
)
dis(x,y)
dis(x,y)最大呢?
我们引入“树的直径”。
树的直径:
树的直径的定义
树上最长的一条路。
树的直径的性质
- 这条路的两个端点一定是叶结点
- 这条路一定经过根节点
证明:
现在我们要证明任意一个点到树的直径的两个端点(其中一个)的距离最远。
我们假设
u
u
u和
v
v
v是树的直径上的两个端点,
x
x
x为任意一个结点。
如下:
我们用反证法。
假设有一个结点
y
y
y,并且满足
x
x
x与结点
y
y
y的距离还要比
x
x
x与
v
v
v的距离远。
如下:
也就是蓝色线比绿色线要长。
那么我们把公共部分删掉。得:
这时候在把线延长至
u
u
u点。得:
上面这张图显示:
d
i
s
(
u
,
y
)
>
d
i
s
(
u
,
v
)
dis(u,y)>dis(u,v)
dis(u,y)>dis(u,v)。
但是我们知道
d
i
s
(
u
,
v
)
dis(u,v)
dis(u,v)是最长路径,怎么可能还比它大呢?
所以,有矛盾。
因此得出,任意一个点到树的直径的两个端点(其中一个)的距离最远。
那么我们直接求出直径端点到每个点的距离,再比较就行了。
得分情况:
得了
48
48
48分,对了前
2
2
2个点。
改题后
100
100
100分。
第三题
题目:
方法:
对于子任务 1 1 1
我们可以直接用状压 d p dp dp来做,时间复杂度为 O ( 2 n × p o l y ( n ) ) O(2^n\times poly(n)) O(2n×poly(n))。
对于子任务 2 2 2
可以优化,时间复杂度为 O ( n 4 ) O(n^4) O(n4),可以过。
对于子任务 3 3 3
对上面的方法进行前缀和优化,时间复杂度为 O ( n 3 ) O(n^3) O(n3)。
对于子任务 4 4 4
可以先用完全背包预处理,时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
题解图片
得分情况:
考试时没有做。
改题之后答案错误,还是
0
0
0分。
第四题
题目:
方法:
对于子任务 1 1 1和 2 2 2
首先有一个暴力算法。记
A
(
i
,
j
)
A(i,j)
A(i,j)为当前还有
i
i
i点行动值,上轮的行动值为
j
j
j时的胜败情况,可以使用动态规划
O
(
n
2
)
O(n^2)
O(n2)计算出所有的
h
m
h_m
hm。
A
(
i
−
k
,
k
)
→
A
(
i
,
j
)
A(i-k,k)\rightarrow A(i,j)
A(i−k,k)→A(i,j)
计算 h m h_m hm
首先,如果
m
m
m为奇数,那么人类方只要在第一轮中只付出一点行动值就能获胜,因为接下来双方都只能每轮付出一点行动值。
而如果
m
m
m为偶数,那么人类方第一轮的行动值必须为偶数,否则轮到病毒方时剩余行动值就会变成奇数。由此我们得出,如果
m
m
m为偶数,双方每次的行动值都一定为偶数。那么只要把每两点行动值合并,我们就能得到
h
2
m
=
2
h
m
h_{2m}=2h_m
h2m=2hm。
我们可以得到
h
m
=
{
1
,
m
=
2
n
+
1
2
h
n
,
m
=
2
n
h_m=\begin{cases} 1,{m=2n+1} \\ {2h_n},{m=2n} \end{cases}
hm={1,m=2n+12hn,m=2n
不难得出
h
m
=
max
2
k
∣
m
2
k
h_m=\max_{2^k|m}{2^k}
hm=max2k∣m2k,即
h
m
=
l
o
w
b
i
t
(
m
)
h_m=lowbit(m)
hm=lowbit(m)。
注:
l
o
w
b
i
t
(
x
)
lowbit(x)
lowbit(x)是
x
x
x的二进制表达式中最低位的
1
1
1所对应的值。
对于子任务 3 3 3
直接用 O ( n ) O(n) O(n)计算出所有 h m h_m hm。
对于子任务 4 4 4或 5 5 5
没有看懂 ,大佬请谅解。
题解图片
得分情况:
比赛时没做。
改题之后
10
10
10分。
第五题
题目:
方法:
国家队层次的题目,没有读懂。
正解:线段树+凸包。
题解图片: