Problem
有一排(n(nleq 10^9))个球,定义一个组可以只包含一个球或者包含两个相邻的球。现在一个球只能分到一个组中,求从这些球中取出(k(k<2^{15}))组的方案数。
Sol1(较优)
设(f_{i,j})表示前(i)个数选了(j)组的方案数。有:
[f_{i,j}=f_{i-1,j}+f_{i-1,j-1}+f_{i-2,j-1}
]
构造生成函数
[F_k(x)=sum_{igeq 0} f_{k,i}x^i
]
由递推式,得
[F_i(x)=(1+x)F_{i-1}(x)+xF_{i-2}(x)
]
边界(F_0(x)=1,F_1(x)=1+x)
对于形如(f_i=af_{i-1}+bf_{i-2})的数列,可以得到其通项公式为
[f_n=Ax_1^n+Bx_2^n
]
其中(x_1,x_2)为方程(x^2=ax+b)的两根,(A,B)通过待定系数法求得。
暴力求解递推式,得到
[F_k(x)=frac{t_1^{k+1}-t_2^{k+1}}{sqrt{x^2+6x+1}}
]
其中(t_1,t_2)为方程(t^2=(1+x)t+x)的两根,这里(t_1)是正根,为(dfrac{1+x+sqrt{x^2+6x+1}}2)
注意到(t_2^{n+1}equiv 0pmod{x^{n+1}}),故最终答案
[F_{k}(x)=frac1{sqrt{x^2+6x+1}}left(frac{1+x+sqrt{x^2+6x+1}}2
ight)^{n+1}
]
复杂度(mathcal O(klog k))
Sol2(较劣)
(n)的范围很大,考虑对(n)下手。
首先,考虑合并两段序列时答案。设左边一段长度为(a),右边一段长度为(b),假设没有组跨过两段,则选取(k)组的方案数为
[sum_{i=0}^kf_{a,i}f_{b,k-i}
]
如果跨过中间,方案数为
[sum_{i=0}^{k-1}f_{a-1,i}f_{b-1,k-i-1}
]
总方案数为
[f_{a+b,k}=sum_{i=0}^kf_{a,i}f_{b,k-i}+sum_{i=0}^{k-1}f_{a-1,i}f_{b-1,k-i-1}
]
还是用上文的生成函数,得到
[F_{a+b}(x)=F_a(x)F_b(x)+xF_{a-1}(x)F_{b-1}(x)
]
代入特定的值
[egin{cases}
F_{2n}(x)=F_n^2(x)+xF_n(x)F_{n-1}(x)\
F_{2n-1}(x)=F_n(x)F_{n-1}(x)+xF_{n-1}^2(x)\
F_{2n-2}(x)=F_{n-1}^2(x)+xF_{n-1}(x)F_{n-2}(x)
end{cases}
]
发现维护({F_{n-2}(x),F_{n-1}(x),F_n(x)})可以得到({F_{2n-2}(x),F_{2n-1}(x),F_{2n}(x)})
最后将(k)二进制分解,运用倍增以及上面的公式得到答案,复杂度(mathcal O(klog klog n)),多出了(log n)的复杂度。当然,直接对Sol1的递推式使用矩阵加速同样可以做到这个复杂度,其与Sol2无本质区别。