ACL Beginner Contest F(Heights and Pairs)题解——分治NTT

Description

一个序列有2n2n2n个数,现在你要在这个序列中配得nnn个无序数对,使得每一对的两个数不同且每个数都在恰好111个对中。

请求出合法配对的方案数。注意(1,3)(2,4)(1,3)(2,4)(1,3)(2,4)(2,4)(1,3)(2,4)(1,3)(2,4)(1,3)这两种配对方式是等价的。

请将答案对998244353998244353998244353取模

n≤50000,ai≤105n≤50000,a_i≤10^5n50000,ai105

Solution

考虑dpdpdp

如果按照整个序列去进行dpdpdp的话很难设计出合理的状态,所以考虑开桶dpdpdp,并令viv_ivi表示第iii个桶的大小。根据题意,每一个桶中的数不能进行匹配,不难得到状态设计与状态转移:

dpi,jdp_{i,j}dpi,j表示看到第iii个桶(即已经处理了111iii号桶),还剩jjj未匹配的方案数

状态转移如下:
dpi,j=∑k=0vi Cvik Aj−(vi−k)+kk dpi−1,j−(vi−k)+kdp_{i,j}=\sum_{k=0}^{v_i}\ C_{v_i}^k\ A_{j-(v_i-k)+k}^k\ dp_{i-1,j-(v_i-k)+k}dpi,j=k=0vi Cvik Aj(vik)+kk dpi1,j(vik)+k

解释一下这个状态转移。kkk枚举的是iii这个桶内与前面匹配掉的数的数量CvikC_{v_i}^kCvik表示在第iii个桶中选择kkk个与前面进行匹配。由于看到第iii个桶还剩jjj个数未匹配,第iii个桶本身对“未匹配的量”的贡献是vi−kv_i-kvik,并且前面还要多留kkk个数与第iii个桶选中的数进行匹配,所以之前未匹配的数的数量应该是j−(vi−k)+kj-(v_i-k)+kj(vik)+k。在这个里面选kkk个数与第iii个桶中选定的kkk进行匹配的方案数为Aj−(vi−k)+kkA_{j-(v_i-k)+k}^kAj(vik)+kk

每次暴力转移的时间复杂度是O(n3)O(n^3)O(n3)的,严重超时。我们先尝试将它优化到O(n2)O(n^2)O(n2)或类O(n2)O(n^2)O(n2)

我们拆开状态转移式中的括号并观察:

dpi,j=∑k=0vi Cvik Aj−(vi−k)+k dpi−1,j−(vi−k)+kdp_{i,j}=\sum_{k=0}^{v_i}\ C_{v_i}^k\ A_{j-(v_i-k)+k}\ dp_{i-1,j-(v_i-k)+k}dpi,j=k=0vi Cvik Aj(vik)+k dpi1,j(vik)+k

dpi,j=∑k=0vi Cvik Aj−vi+2k dpi−1,j−vi+2kdp_{i,j}=\sum_{k=0}^{v_i}\ C_{v_i}^k\ A_{j-v_i+2k}\ dp_{i-1,j-v_i+2k}dpi,j=k=0vi Cvik Ajvi+2k dpi1,jvi+2k

考虑将dpi−1dp_{i-1}dpi1翻转,就得到了一个卷积的形式。每次跑一遍NTTNTTNTT,时间复杂度优化到O(n2log⁡n)O(n^2 \log n)O(n2logn)

但是我们依然不满意。不难发现这个状态转移可以用cdq分治来优化,即分治NTT。每次我们递归左半边,跑一遍NTT处理左半边对右半边的贡献再往后边递归。由于递归的深度最大是log⁡n\log nlogn的,所以卷积的次数为nlog⁡nn \log nnlogn次,总时间复杂度为O(nlog⁡2n)O(n \log^2 n)O(nlog2n)

NTT txdy!

Summary

在本题中,我们巧妙设计了dpdpdp状态,发现翻转后是一个卷积的形式,从而采用分治NTT将时间复杂度优化到了O(n2log⁡n)O(n^2 \log n)O(n2logn)

可以说这是一道比较套路的题,唯一较为灵活的就是dpdpdp的状态设计以及状态转移。分治NTT出来得比较自然,可惜蒟蒻(我)在想这题的时候并不会分治NTT,是在看了别人的题解之后才悟懂。

感觉这题放在ABC的F题是不是太过分了啊???

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值