整数划分问题的高效解法 (n logn)

一般此类问题可以看做是一个背包问题,不过有更优秀的解法。

1.数字互不相同(51nod1201)( O(nn) O ( n n ) )

注意到最多有 O(n) O ( n ) 个数相加,则记 fi,j f i , j 表示 j j 个数和为 i i 的方案数。我们讨论一个方案的最小值是否为1,如果为1,则 fi1,j1fi,j f i − 1 , j − 1 → f i , j ,否则我们把每一个数减去1, fij,jfi,j f i − j , j → f i , j

即: fi,j=fij,j1+fij,j f i , j = f i − j , j − 1 + f i − j , j , 时间复杂度

Code

2.数字可以重复 (51nod1259)( O(nn)/O(nlogn) O ( n n ) / O ( n log ⁡ n ) )

O(nn) O ( n n ) 解法

注意到 n ≥ n 的数最多出现 n n 次,那我们分开做。
前面做背包,后面同样考虑最小的数,若为 n n 那么 fiB,j1fi,j f i − B , j − 1 → f i , j ,否则 fij,jfi,j f i − j , j → f i , j
时间复杂度为 O(nn) O ( n n )
Code

O(nlogn) O ( n log ⁡ n ) 解法

利用分拆数和五边形数的关系,我们得到一个卷积递推式。
fg=f1f=11g f ∗ g = f − 1 ⇒ f = 1 1 − g
其中 g3k2±k2=(1)k+1 g 3 k 2 ± k 2 = ( − 1 ) k + 1
(modxn+1) ( mod x n + 1 ) 意义下做多项式求逆即可,时间复杂度 O(nlogn) O ( n log ⁡ n )
(为了方便,这里对998244353取模,对于任意模数可以考虑实数FFT或者三模数NTT,由于常数较大这里跳过)。
Code
也可以直接递推,易知复杂度为 O(nn) O ( n n )

你可能感兴趣的:(分块,ntt,fft)