51Nod1597 有限背包计数问题

传送门

很早就看到学长们说这是OEIS A052335,寒假做完这道题之后就像试一试能不能推出来$O(nlog n)$的做法,但是当时FFT刚入门,加之英语不好,并没有看出来什么有用的信息,这个坑就这么留着了。

今天下午突然心血来潮想再推一下,就重新翻开了OEIS A052335,稍微推了点时间,还是推出来了,并且发现推导过程并不难。

看网上并没有多少这么做的啊,那我就写一发好了。

(ps:以下所有运算均在$mod x^n$意义下进行,推导的时候要注意有的运算得出的无限项多项式不能对$x^n$取模,因此必须只用到结果可以对$x^n$取模的运算)

万能的OEIS告诉我们这个数列的生成函数是

egin{align}A(x)=prod_{ige 1}frac{1-x^{i(i+1)}}{1-x^i}end{align}

那个$prod$太碍事,不妨两边取一下$ln$,那么就有

egin{align}ln A(x)=sum_{ige 1}left(lnleft(1-x^{i(i+1)} ight)-lnleft(1-x^i ight) ight)end{align}

根据泰勒展开,有

egin{align}ln(1-x)=-sum_{ige 1}frac{x^i}iend{align}

代入上式得

egin{align}ln A(x)=sum_{kge 1}left(sum_{ige 1}frac{x^{ik}}i-sum_{ige 1}frac{x^{ik(k+1)}}i ight)end{align}

也即

egin{align}A(x)=expleft(sum_{kge 1}left(sum_{ige 1}frac{x^{ik}}i-sum_{ige 1}frac{x^{ik(k+1)}}i ight) ight)end{align}

右边的式子是可以通过枚举每个数的倍数$O(nlog n)$搞出来的,对右边跑多项式$exp$即可求出$A(x)$,复杂度$O(nlog 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计算最后的卷积就可以了,所以说这个做法算是彻底废了……

原文地址:https://www.cnblogs.com/hzoier/p/6624117.html