Source:
FJWC2018正式赛
Problem
T1 三元组
题意
求多少个三元组 (a,b,c) ( a , b , c ) 满足 a+b2≡c3(modk) a + b 2 ≡ c 3 ( mod k ) , T T 组数据。
数据范围
题解
30分解法
枚举 a,b,c a , b , c ,判断是否满足式子。
复杂度 O(T×n3) O ( T × n 3 ) 。
60分解法
先不考虑 modk mod k ,则等式化为 a+b2=c3 a + b 2 = c 3 。
固定 b b ,根据 ,可以得到 c c 的取值范围是 。
固定 c c ,枚举 ,统计 c c 落在 的个数即三元组个数。
对于 modk mod k 的情况处理方法类似。
首先考虑 [b2+1,b2+b]modk [ b 2 + 1 , b 2 + b ] mod k 之后会跨越 [0,k−1] [ 0 , k − 1 ] 多次,其次再分别处理剩下的不完整区间。
跨越 ⌊ik⌋ ⌊ i k ⌋ 个完整区间 [0,k−1] [ 0 , k − 1 ] 后,剩余的不完全区间有以下两种情况:
第一种情况,即 0≤(b2+1)modk≤(b2+b)modk≤k−1 0 ≤ ( b 2 + 1 ) mod k ≤ ( b 2 + b ) mod k ≤ k − 1 ,即剩下相交的部分;
第二种情况,即 0≤(b2+b)modk≤(b2+1)modk≤k−1 0 ≤ ( b 2 + b ) mod k ≤ ( b 2 + 1 ) mod k ≤ k − 1 ,即剩下两边的部分。
那么对于第一种情况,处理 [(b2+1)modk,(b2+b)modk] [ ( b 2 + 1 ) mod k , ( b 2 + b ) mod k ] ;
对于第二种情况,分别处理 [0,(b2+b)modk] [ 0 , ( b 2 + b ) mod k ] 和 [(b2+1)modk,k−1] [ ( b 2 + 1 ) mod k , k − 1 ] 。
从 1 1 到 枚举 b b ,每次对区间 加一,累加 i3 i 3 的值即最后的三元组数量。
复杂度 O(T×n2) O ( T × n 2 ) 。
100分解法
根据数据范围,考虑 O(nlogn) O ( n log n ) 的数据结构维护区间。
想到树状数组/线段树。
由于是区间加法+单点查询,因此选择树状数组进行维护。
复杂度 O(T×nlogn) O ( T × n log n ) 。
T2 攻略
题意
一棵树有 n n 个结点,每个结点有权值 。现有 m m 条从根到叶子结点的路径,求它们路径结点的最大权值和(每个点权值只计算一次)。
数据范围
, 1≤Wi≤231−1 1 ≤ W i ≤ 2 31 − 1
题解
40分解法
树上背包, Fi,j F i , j 表示结点 i i 为根的子树, 条路径的最大权值和。
则 Fi,j=max{Fi,k+Fv,j−k}+Wi F i , j = max { F i , k + F v , j − k } + W i ,其中 v v 为 的儿子, 0≤k≤j≤min{sizei,m} 0 ≤ k ≤ j ≤ min { s i z e i , m } 。
复杂度 O(n×m) O ( n × m ) 。
100分解法
考虑贪心,每次选择当前树上权值和最大的那条链作为路径,然后将该链上的所有结点权值清零,往复 m m 次。
对原树进行深度优先遍历时,按照访问顺序对所有叶子节点进行编号,如此易得原树中任意一棵子树的叶子节点编号是连续的。
那么在深度优先遍历时记录每个节点访问时的叶子结点个数和访问结束(回溯)前的叶子结点个数(即最新编号),就可以得到它的子树中叶子节点的编号范围 。
使用线段树维护路径权值和的最大值及对应叶子节点编号,每次取根节点记录的最大值,并通过记录的叶子节点编号和父节点编号来一步步更新线段树的维护的权值和。
预处理复杂度 O(n) O ( n ) ,查询复杂度 O(1) O ( 1 ) ,更新复杂度 O(logn) O ( log n ) ,总复杂度 O(m×logn) O ( m × log n ) 。
T3 迂回
题意
给定一个有向图,求图中长度小于 k k 的环个数()。
图中没有自环,旋转后相同的环也算作不同的环(即环中点的排列不完全相同即可)。
数据范围
1≤n≤100,k≤106,m≤109 1 ≤ n ≤ 100 , k ≤ 10 6 , m ≤ 10 9
题解
30分解法
计算每个点在第 1 1 到第 步到每个点的方案数。所有自环(回到自己)的方案数的之和,即为总环数。
复杂度 O(n3×k) O ( n 3 × k ) 。
100分解法
图 G={a,b,c} G = { a , b , c } 中, num(a,b)×num(b,c)=num(a,c) n u m ( a , b ) × n u m ( b , c ) = n u m ( a , c ) , num(a,b) n u m ( a , b ) 即 a a 到 的路径数量。
我们可以发现 num(a,c)=∑num(a,b)×num(b,c) n u m ( a , c ) = ∑ n u m ( a , b ) × n u m ( b , c ) ,这和矩阵乘法完全相同。
考虑矩阵乘法,记 Aki,i A i , i k 为原始矩阵 A A 连乘 次后 (i,i) ( i , i ) 的值,则 ∑k−1i=1∑nj=1Aij,j ∑ i = 1 k − 1 ∑ j = 1 n A j , j i 为总方案数。
考虑分治计算上式,记 P(x) P ( x ) 为 ∑xi=1∏i1A ∑ i = 1 x ∏ 1 i A ,则
若 x x 为偶数,则 ;
否则 P(x)=P(x/2)+Ax×P(x/2)+Ax P ( x ) = P ( x / 2 ) + A x × P ( x / 2 ) + A x 。
那么上式可以在 O(n3×logk) O ( n 3 × log k ) 的时间内解出。
总复杂度 O(n3×logk) O ( n 3 × log k ) 。
总结
考场状态及得分情况
考场上T1直接 O(n3) O ( n 3 ) 暴力,T2 O(n×m) O ( n × m ) 树形dp,T3 O(8×n3×logk) O ( 8 × n 3 × log k ) 构建 n n <script type="math/tex" id="MathJax-Element-99">n</script> 个虚拟点跑矩阵快速幂。
得分30+40+100=170,rk2。
问题
T1和T2都没有想得很清楚。
T1写完暴力之后就没有再思考,止步复杂度最高的暴力。
T2的贪心想到了但是没有去尝试,保守地写了个能拿到40分的树形dp。
T3常数有点大,好在最后A了,但是花的时间有点太长。
总的来说还可以,靠着T3把T1没拿到的一些分补上了。