整数划分
先给出几个定义:
一、整数的划分
将正整数 n n n 拆分成若干个正整数的和就叫做整数的划分。
二、整数的 k k k 划分
即将其拆分成若干个不大于 k k k 的正整数的和。
三、整数的 k k k 分部划分
即将其拆分成 k k k 个正整数的和。
四、有序划分和无序划分
有序划分即顺序有关的划分,例如 1 + 2 1+2 1+2 与 2 + 1 2+1 2+1 被视为 3 3 3 的不同的划分。而无序划分则是顺序无关的。
五、划分数
即对应条件下的划分的方案数。
在本文中,将 n n n 的无序划分数记为 B n B_n Bn ,将 n n n 的无序 k k k 划分数记为 B k ( n ) B_k(n) Bk(n) ,将 n n n 的无序 k k k 分部划分数记为 B n , k B_{n,k} Bn,k 。
本文的重点在于如何求各种不同的划分数。
有序划分
整数 n n n 的 k k k 分部划分数为 C n − 1 k − 1 C_{n-1}^{k-1} Cn−1k−1 。
这不难理解: f n , k = ∑ i = 1 n f n − i , k − 1 f_{n,k}=\sum \limits _{i=1}^n f_{n-i,k-1} fn,k=i=1∑nfn−i,k−1 ,平凡的有其值等于 C n − 1 k − 1 C_{n-1}^{k-1} Cn−1k−1 。
n n n 的有序划分数为 ∑ i = 1 n C n − 1 k − 1 = 2 n − 1 \sum\limits_{i=1}^nC_{n-1}^{k-1}=2^{n-1} i=1∑nCn−1k−1=2n−1 。
而 n n n 的有序 k k k 划分数满足 f n , k = ∑ i = 1 k f n − i , k f_{n,k}=\sum\limits_{i=1}^kf_{n-i,k} fn,k=i=1∑kfn−i,k ,是一个经典的线性递推式。不过由于其特征多项式为 x k + 1 − 2 x k + 1 x − 1 \frac{x^{k+1}-2x^k+1} {x-1} x−1xk+1−2xk+1 ,可以做到 O ( n ) O(n) O(n) 取模,因此可以做到 O ( n ) O(n) O(n) 或 O ( k log k log n ) O(k \log k \log n) O(klogklogn) 求值。
有序划分较易理解,这里不再赘述。本文重点在于下面的无序划分。
无序划分
动态规划法
先从朴素的角度切入。
考虑 n n n 的 k k k 划分。
我们可以使用 k k k ,也可以不使用 k k k 。
因此有 B k ( n ) = B k ( n − k ) + B k − 1 ( n ) B_k(n)=B_k(n-k)+B_{k-1}(n) Bk(n)=Bk(n−k)+Bk−1(n) 。
注意当 n ≥ k n \ge k n≥k 有 B k ( n ) = B k ( k ) B_{k}(n)=B_{k}(k) Bk(n)=Bk(k) 。
现在考虑无序 k k k 分部划分。
我们知道对于其任意一个合法的划分有 ∑ i = 1 k a i = n \sum\limits_{i=1}^{k}a_i=n i=1∑kai=n 且 a i ≥ 1 a_i\ge 1 ai≥1。
由于 a i ≥ 1 a_i \ge 1 ai≥1 的条件不好处理,因此我们令 b i = a i − 1 b_i=a_i-1 bi=ai−1 。
则有 ∑ i = 1 k b i = n − k , b i ≥ 0 \sum\limits_{i=1}^{k}b_i=n-k,b_i \ge 0 i=1∑kbi=n−k,bi≥0 。
我们可以考虑将值为 0 0 0 的去掉。
因此 ∑ i = 1 j b i = n − k , b i ≥ 1 , 1 ≤ j ≤ k \sum\limits_{i=1}^{j}b_i=n-k,b_i\ge1,1\le j\le k i=1∑jbi=n−k,bi≥1,1≤j≤k 。
由于顺序无关,我们可以将任意一种 a a a 的方案以此法一一映射到 b b b 的一种方案。
因此有 B n , k = ∑ i = 1 k B n − k , i B_{n,k}=\sum\limits_{i=1}^{k} B_{n-k,i} Bn,k=i=1∑kBn−k,i 。
这样直接转移是 O ( n k 2 ) O(nk^2) O(nk2) 的。
将转移方程稍微变形:
B n , k = ∑ i = 1 k B n − k , i = ∑ i = 1 k − 1 B n − k , i + B n − k , k = B n − 1 , k − 1 + B n − k , k B_{n,k}=\sum_{i=1}^{k} B_{n-k,i}=\sum_{i=1}^{k-1}B_{n-k,i}+B_{n-k,k}=B_{n-1,k-1}+B_{n-k,k} Bn,k=i=1∑kBn−k,i=i=1∑k−1Bn−k,i+Bn−k,k=Bn−1,k−1+Bn−k,k
这样就是 O ( n k ) O(nk) O(nk) 了。
我们发现这个递推式与 k k k 划分是向一致的,只是这两个数列初始边界差异才导致了两个数列的差异。我们尝试考虑两个数列的联系:
无序性实际上加一个限制 a i ≤ a i + 1 a_i \le a_{i+1} ai≤ai+1 即可。
将一中拆分方案抽象为图形,那么这实际上就是一张各列高度递增的网格图,由于平面的特性我们可以将其旋转 90 ° 90 \degree 90° 得到一个新的方案。
实质上我们在做的就是:记 b i = ∑ j = 1 k [ a j ≥ i ] b_i=\sum\limits_{j=1}^{k}[a_j\ge i] bi=j=1∑k[aj≥i] ,则 ∑ j = 1 max { a } b i = n \sum\limits_{j=1}^{\max\{a\}}b_i=n j=1∑max{ a}bi=n 且 b 1 = k , b i ≥ b i + 1 b_1=k,b_i\ge b_{i+1} b1=k,bi≥bi+1 。
因此我们可以得到 n n n 的无序 k k k 分部划分数等于 n n n 的最大分部值为 k k k 的方案数,于是就有 B n , k = B k ( n ) − B k − 1 ( n ) B_{n,k}=B_{k}(n)-B_{k-1}(n) Bn,k=Bk(n)−Bk−1(n) 。
若 b 2 = k b_2 =k b2=k 则 a i ≥ 2 a_i \ge 2 ai≥2 ,我们可以令 a i a_i ai 都减去 1 1 1 。否则我们可以在 b b b 中去掉 b 1 = k b_1=k b1=k ,这样就得到了 B n , k = B n − k , k + B n , k − 1 B_{n,k}=B_{n-k,k}+B_{n,k-1} Bn,k=Bn−k,k+Bn,k−1 。
当然根据 B n , k = B k ( n ) − B k − 1 ( n ) B_{n,k}=B_{k}(n)-B_{k-1}(n) Bn,k=Bk(n)−Bk−1(n) 也能得到以上递推式,这也很好解释了为何两个数列的初始边界有所不同。
上述算法的复杂度较大,我们尝试继续优化。
生成函数法
我们尝试从生成函数的角度切入。
先考虑 n n n 的 k k k 划分。
我们可以选任意多的 1 1 1 到 k k k 之间的数,且需要使之总和为 n n n 。两种方案不同等价于任意一个数选的个数不同。
因此我们可以构造 ∑ j = 0 ∞ x i j \sum\limits_{j=0}^{\infty}x^{ij} j=0∑∞xij 表示选取 j j j 个 i i i 的方案。
那么
∑ n = 0 ∞ B k ( n ) x n = ∏ i = 1 k ( ∑ j = 0 ∞ x i j ) = 1 ∏ i = 1 k ( 1 − x i ) \sum\limits_{n=0}^{\infty} B_{k}(n)x^n=\prod_{i=1}^{k}(\sum\limits_{j=0}^{\infty}x^{ij})=\frac{1} {\prod_{i=1}^{k}(1-x^i)} n=0∑∞Bk(n)xn=i=1∏k(j=0∑∞xij)=∏i=1k(1−xi)1
显然我们可以转为线性递推来解决这个问题,其特征多项式为 ∏ i = 1 k ( x i − 1 ) \prod_{i=1}^{k}(x^i-1) ∏i=1k(xi−1) 。并且我们可以根据 x n   m o d   ( x i − 1 ) = x n   m o d   i x^n \bmod (x^i-1)=x^{n \bmod i} xnmod(xi−1)=xnmodi 列出同余方程组。
复杂度 O ( k 2 log 2 k ) O(k^2\log^2 k) O(k2log2k) ,注意这是一个与 n n n 无关的复杂度。
但这样 k k k 较大而 n n n 的阶比 k k k 并不是高很多的时候效率较低。考虑是否有其他的处理方式。
暴力乘法是 O ( n k ) O(nk) O(nk) 的,无法继续优化,尝试变换思路。
事实上我们只需要求 f ( x )   m o d   x n + 1 f(x) \bmod x^{n+1} f(x)modxn+1 。超过 n + 1 n+1 n+1 的项是无需计算的。
由于乘法无法继续优化,且我们只需要取函数的前几项,因此我们对函数取对数转为加法。
ln f ( x ) = ln 1 ∏ i = 1 k ( 1 − x i ) = − ∑ i = 1 k ∑ j = 1 ∞ − x i j j = ∑ i = 1 k ∑ j = 1 ∞ x i j j \ln f(x)=\ln \frac{1} {\prod_{i=1}^{k}(1-x^i)} =-\sum_{i=1}^{k}\sum_{j=1}^{\infty} \frac{-x^{ij}} {j}=\sum_{i=1}^{k}\sum_{j=1}^{\infty} \frac{x^{ij}} {j} lnf(x)=ln∏i=1k(1−xi)1=−i=1∑kj=1∑∞j−xij=i=1∑kj=1∑∞jxij
我们只需要计算前 n + 1 n+1 n+1 项,因此求 ln f ( x ) \ln f(x) lnf(x) 的复杂度为 O ( n log k ) O(n\log k) O(nlogk) 。
最后多项式 exp \exp exp 即可。总复杂度 O ( n log n ) O(n \log n) O(nlogn) 。
而根据 B n , k = B k ( n ) − B k − 1 ( n ) B_{n,k}=B_{k}(n)-B_{k-1}(n) Bn,k=Bk(n)−Bk−1(n) ,我们有 n n n 的 k k k 分部划分的生成函数为
∑ n = 0 ∞ B n , k x n = ∑ n = 0 ∞ B k ( n ) x n − ∑ n = 0 ∞ B k − 1 ( n ) x n = ( 1 1 − x k − 1 ) 1 ∏ i = 1 k − 1 ( 1 − x i ) = x k ∏ i = 1 k ( 1 − x i ) \sum\limits_{n=0}^{\infty} B_{n,k}x^n=\sum\limits_{n=0}^{\infty} B_{k}(n)x^n-\sum\limits_{n=0}^{\infty} B_{k-1}(n)x^n=(\frac{1}{1-x^k}-1)\frac{1} {\prod_{i=1}^{k-1}(1-x^i)}=\frac{x^k} {\prod_{i=1}^{k}(1-x^i)} n=0∑∞Bn,kxn=n=0∑∞Bk(n)xn−n=0∑∞Bk−1(n)xn=(1−xk1−1)∏i=1k−1(1−xi)1=∏i=1k(1−xi)xk
求法与 k k k 划分是一样的。
根据 B n = B ∞ ( n ) B_n=B_{\infty}(n) Bn=B∞(n) 有 n n n 划分数的生成函数为
∑ n = 0 ∞ B n x n = 1 ∏ i = 1 ∞ ( 1 − x i ) = 1 1 + ∑ i = 1 ∞ ( − 1 ) i x i ( 3 i ± 1 ) 2 \sum_{n=0}^{\infty}B_nx^n=\frac{1} {\prod_{i=1}^{\infty}(1-x^i)}=\frac{1}{1+\sum\limits_{i=1}^{\infty}(-1)^ix^{\frac{i(3i\pm1)} {2}}} n=0∑∞Bnxn=∏i=1∞(1−xi)1=1+i=1∑∞(−1)ix2i(3i±1)1
这里用到了五边形数。
可以使用 O ( n n ) O(n \sqrt n) O(nn) 的递推或 O ( n log n ) O(n\log n) O(nlogn) 的多项式求逆。但要注意这个问题不能转化为线性递推问题。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/78296.html