51Nod1597 有限背包计数问题
很早就看到学长们说这是OEIS A052335,寒假做完这道题之后就像试一试能不能推出来$O(n\log n)$的做法,但是当时FFT刚入门,加之英语不好,并没有看出来什么有用的信息,这个坑就这么留着了。
今天下午突然心血来潮想再推一下,就重新翻开了OEIS A052335,稍微推了点时间,还是推出来了,并且发现推导过程并不难。
看网上并没有多少这么做的啊,那我就写一发好了。
(ps:以下所有运算均在$\mod x^n$意义下进行,推导的时候要注意有的运算得出的无限项多项式不能对$x^n$取模,因此必须只用到结果可以对$x^n$取模的运算)
万能的OEIS告诉我们这个数列的生成函数是
\begin{align}A(x)=\prod_{i\ge 1}\frac{1-x^{i(i+1)}}{1-x^i}\end{align}
那个$\prod$太碍事,不妨两边取一下$\ln$,那么就有
\begin{align}\ln A(x)=\sum_{i\ge 1}\left(\ln\left(1-x^{i(i+1)}\right)-\ln\left(1-x^i\right)\right)\end{align}
根据泰勒展开,有
\begin{align}\ln(1-x)=-\sum_{i\ge 1}\frac{x^i}i\end{align}
代入上式得
\begin{align}\ln A(x)=\sum_{k\ge 1}\left(\sum_{i\ge 1}\frac{x^{ik}}i-\sum_{i\ge 1}\frac{x^{ik(k+1)}}i\right)\end{align}
也即
\begin{align}A(x)=\exp\left(\sum_{k\ge 1}\left(\sum_{i\ge 1}\frac{x^{ik}}i-\sum_{i\ge 1}\frac{x^{ik(k+1)}}i\right)\right)\end{align}
右边的式子是可以通过枚举每个数的倍数$O(n\log n)$搞出来的,对右边跑多项式$\exp$即可求出$A(x)$,复杂度$O(n\log n)$。
复杂度很优秀,然而……
我稍微压了一下预处理的常数(NTT和多项式$\exp$的常数没有去压……好吧我承认我比较懒,连预处理$\omega_n$和$\omega$都懒的写……),对于$n=100000$的极限数据是可以在1.3s不到的时间内出解的,然而我写的分块只需要0.3s不到……况且这还是在$\mod 998244353$的时候,如果是原题的$\mod 23333333$的话我还得写三模数NTT,早就TLE了……并且即使对于高达$3000000$的数据范围,多项式$\exp$用时52s,分块用时48s,根本卡不动分块,所以说这个做法只有理论上的意义……
这个故事告诉我们:多项式$\exp$常数炸飞天,能不用就不用……
ps:其实有脑补过输出$1$~$n$的所有答案来卡分块,但后来发现分块计算出$n$的答案之后用FFT计算最后的卷积就可以了,所以说这个做法算是彻底废了……