The 2019 China Collegiate Programming Contest Harbin Site

就是说,永远不会博弈枯了枯了。

来写点一套题的题解吧(如果我会的话。

A - Artful Paintings

场A(-6)。

考虑染球个数的前缀和,会发现满足一些不等式: s i − s i − 1 ≥ 0 , s i − s i − 1 ≤ 1 , s r i − s l i − 1 ≥ k i , s n − ( s r i − s l i − 1 ) ≥ k i s_i-s_{i-1} \ge 0,s_i-s_{i-1} \le 1,s_{r_i}-s_{l_i-1} \ge k_i,s_{n}-(s_{r_i}-s_{l_i-1}) \ge k_i sisi10,sisi11,srisli1ki,sn(srisli1)ki 。然后会发现有个s_n的东西弄不掉,我们就想办法把它变成常数。

发现可以二分 s n s_n sn ,于是它就变成常数了,并且要满足 s n − s 0 = m i d s_n-s_0=mid sns0=mid ,然后就是差分约束,跑个 spfa \text{spfa} spfa 即可。

效率: O ( n m log ⁡ n ) O(nm\log n) O(nmlogn)

要剪枝,不然会T。

B - Binary Numbers

场A(-4)。

F ( ) F() F() 相当于求两个数写成二进制形式下的 lcp \text{lcp} lcp

显然,对于 ( i , j ) (i,j) (i,j) i < j i<j i<j ,如果固定 i i i ,那么 j j j 越大的话它们的 lcp \text{lcp} lcp 会越小。

因此,我们其实只需要考虑对于 i − 1 i-1 i1 i i i 区间,要满足 F ( a i − 1 , r i − 1 ) ≥ F ( a i , r i − 1 ) , F ( a i − 1 , l i ) ≤ F ( a i , l i ) F(a_{i-1},r_{i-1}) \ge F(a_i,r_{i-1}),F(a_{i-1},l_i) \le F(a_i,l_i) F(ai1,ri1)F(ai,ri1),F(ai1,li)F(ai,li)

因此我们考虑 dp \text{dp} dp f i f_i fi 表示以 i i i 为结尾的答案,那么对于 i i i ,能够转移到它的点一定是一段区间,而且 i i i 越大,区间只会往左移。因此记个前缀和就好了。

效率: O ( m 2 m ) O(m2^m) O(m2m)

注意模数是 1 e 8 + 7 1e8+7 1e8+7

C - Competition in Swiss-system

场未A。

模拟,题目太长,没时间打。

D - Driverless Car

场未A,乍一眼看应该是计算几何,不会。

E - Exchanging Gifts

场A(-4)。

考虑如果知道了最后一个串怎么求答案。那就只要看颜色最多的数量是否达到总长的一半即可,如果没达到就是总长,否则就是去掉最多颜色数的两倍。

因此我们其实只要知道每个颜色在最后一个串出现多少次即可,那其实也就是要知道每个操作为 1 1 1 的串对于最后一个串的贡献。

因此做个 dp \text{dp} dp 即可。 f i f_i fi 表示第 i i i 个串在最后一个串中出现多少次,然后把它传递给那两个合并串即可。

效率: O ( n l o g n ) O(nlogn) O(nlogn)

场上需要写 fread \text{fread} fread 才能过…大受震撼。

F - Fixing Banners

场1A。

直接 6 ! 6! 6! 判断就好了。

效率: O ( 6 ! × l e n g t h ) O(6!\times length) O(6!×length)

G - Game Store

场未A。以下口胡。

是我不会的 nim-k \text{nim-k} nim-k 游戏了。

如果二进制下,每一位 1 1 1 的个数都是 k + 1 k+1 k+1 的倍数(这题是 3 3 3 的倍数),那么先手必败,否则必胜。

因此, A 如果选择了一些 set \text{set} set ,那么这些 set \text{set} set 里的石堆可以看成向量 a i a_i aiB 要移除一些石堆来确保自己能赢,也就是说,每个 a i a_i ai 最后会剩下 0 / 1 / 2 0/1/2 0/1/2 堆,那其实 B 要做的就是在模 3 3 3 意义下,使得 ∑ k i a i = 0 \sum k_i a_i=0 kiai=0

因此, A 要选的就是 a i a_i ai 的最大权线性无关组。用线性基维护,这里的线性基是对 3 3 3 取模的。具体就是每次到非零位,如果当前位的值比自己小,那就交换并且消高位往下走即可。

然后听说模 3 3 3 很慢,要用 4 4 4 进制来优化常数。

H - Highway Buses

场未A,以下口胡。

最优解只可能在 T = 1 T=1 T=1 T = T m a x T=T_{max} T=Tmax 取,因此做两遍就好了。

搞出一棵生成树,非树边最多 51 51 51 条。

考虑如果只走树边,那么就考虑在i点的答案为 g i g_i gi ,然后我们维护一个堆,按照 g i + c i g_i+c_i gi+ci 从小到大排序,然后每次用堆顶去更新别的点答案。

假设堆顶为 i i i ,那么我们要更新的点 j j j 要满足树上 dis ( i , j ) ≤ f i \text{dis}(i,j) \le f_i dis(i,j)fi 且还没有被更新过。因此我们考虑建出点分树,从i往上走,对于每个点分中心维护一个队列,按照 dis \text{dis} dis 排序,因此我们每次更新队列中的前面一部分的点即可。

现在考虑非树边,如果经过了非树边 ( u , v ) (u,v) (u,v) ,那么一定会经过 u u u 点,那么我们最多有 51 51 51 个这样的点,因此现在原图上跑 51 51 51 次单源最短路。然后在原本的基础上考虑如果 i i i 要更新到 j j j 并且走了非树边,那么我们就枚举关键点,那么能够更新那个 j j j 的要求就是 d i s ( i , u ) + d i s ( u , j ) ≤ f i dis(i,u)+dis(u,j) \le f_i dis(i,u)+dis(u,j)fi ,因此也维护一个队列即可。

打标记使得每个点只进入堆一次,那么效率就是 O ( n l o g n + 51 n ) O(nlogn+51n) O(nlogn+51n)

I - Interesting Permutation

场A(-1)。

先判掉一些非法情况,比如 h i ! = 0 , h n ! = n − 1 , h i > h i + 1 h_i!=0,h_n!=n-1,h_i>h_{i+1} hi!=0,hn!=n1,hi>hi+1

然后我们设前i的答案为 f i f_i fi

如果 h i > h i − 1 h_i>h_{i-1} hi>hi1 的话,那么第 i i i 个数肯定是前 i i i 个数中的最大值或者最小值,因此 f i = f i − 1 × 2 f_i=f_{i-1}\times 2 fi=fi1×2

如果 h i = h i − 1 h_i=h_{i-1} hi=hi1 的话,那第 i i i 个数就是选择了最大值和最小值中的一个数,因此我们再维护最大值和最小值中还有多少数没有被选择即可。

效率: O ( n ) O(n) O(n)

-1是因为 ( s + = f i ) % = P (s+=f_i)\%=P (s+=fi)%=P 写成了 % P \%P %P …枯了枯了。

J - Justifying the Conjecture

场1A。

n < 6 n<6 n<6 无解,否则 n n n 是奇数就是 3 , n − 3 3,n-3 3,n3 ,偶数就是 2 , n − 2 2,n-2 2,n2

K - Keeping Rabbits

场1A。

有生之年我没有被卡精度。

兔子重量的比例不会变,所以每次增加的重量不会变,所以直接加上 k × w i s k \times \frac{w_i}{s} k×swi 即可。

L - LRU Algorithm

场1A。

发现 B = 793999 B=793999 B=793999 P = 1 e 9 + 7 P=1e9+7 P=1e9+7 没有被卡过,以后都用这个。

求出每次加入一个数之后,新的串前缀的 hash \text{hash} hash 值即可。

效率: O ( n 2 ) O(n^2) O(n2)

原本想写 trie \text{trie} trie 树,但是感觉要用 map \text{map} map 存下一个节点就是 n 2 l o g n^2log n2log 的了,于是还是 hash \text{hash} hash 吧。

All in all,打得其实还不错,但是要注意一些细节的东西,而且其实长的题目也不一定就是很难的题目,所以还是最好把题目全读一遍更好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值