多项式

拉格朗日插值

基本流程

对于一个 \(n\) 次函数 \(f(x)\),给出 \(n+1\) 个点值 \((x_i,y_i)\),保证 \(x_i\) 互不相同,求 \(f(k)\)

考虑 crt 的思想,对于第 \(i\) 个点值 \((x_i,y_i)\),构造函数 \(f_i(x)\) 满足 \(f_i(x_i)=y_i\),且对于 \(j\ne i\)\(f_i(x_j)=0\)

\[f_i(x)=\lambda\prod_{j=0,j\ne i}^n(x-x_j)\\ f_i(x_i)=y_i \]

可以推出 \(f_i(x)\) 的表达式

\[f_i(x)=y_i\prod_{j=0,j\ne i}^{n}\frac{x-x_j}{x_i-x_j} \]

所以 \(f(x)\) 的表达式即为所有 \(f_i(x)\) 的和

\[f(x)=\sum_{i=0}^ny_i\prod_{j=0,j\ne i}^n\frac{x-x_j}{x_i-x_j} \]

直接计算时间复杂度为 \(O(n^2)\),用分治 NTT 可以优化到 \(O(n\log^2 n)\)

特殊情况

如果 \(x_i=i\),则 \(f(x)\) 可以变为

\[\begin{aligned} f(x)&=\sum_{i=0}^{n}y_i\frac{x(x-1)\cdots(x-i+1)(x-i-1)(x-i-2)\cdots(x-n)}{i(i-1)\cdots1(-1)(-2)\cdots(i-n)}\\ &=\sum_{i=0}^{n}y_i\frac{p_is_i}{i!(n-i)!(-1)^{n-i}} \end{aligned} \]

其中 \(p_i=\prod\limits_{j=0}^{i-1}(x-j)\)\(s_i=\prod\limits_{j=i+1}^{n}(x-j)\),通过预处理可以 \(O(n)\) 得到,再预处理出阶乘及逆元,整体时间复杂度就是 \(O(n)\)

动态加点

因为

\[f(x)=\sum_{i=0}^ny_i\prod_{j=0,j\ne i}^n\frac{x-x_j}{x_i-x_j} \]

\(g(x)=\prod\limits_{i=0}^n(x-x_i)\)\(h(i)=\prod\limits_{j=0,j\ne i}^n\frac{y_i}{x_i-x_j}\),所以有

\[f(x)=g(x)\sum_{i=0}^{n}h(i) \]

每次加点 \((x_{n+1},y_{n+1})\) 时对于 \(0\le i\le n\)\(h(i)\) 都会乘以 \(\frac{1}{x_i-x_{n+1}}\),然后 \(h(n+1)\) 直接算就行了,所以查询和修改操作都是 \(O(n)\) 的。

例题

[NOIP2020] 微信步数

先把无解判掉,即 \(n\) 步后每一维位移量为 \(0\) 且偏差量不超过 \(w_i\)

转换问题,即枚举走的步数,统计有多少种方案不会走出去。进一步发现对于每一维,可供选择的位置是一段区间 \([l_i,r_i]\),所以方案数即 \(\prod(r_i-l_i+1)\)。可以通过统计位移量 \(s_i\) 的极值来计算。时间复杂度最大是 \(O(nkV)\)

考虑优化,令 \(l_{i,j}\) 为第一轮经过 \(i\) 步第 \(j\) 维位移量的最小值,\(r_{i,j}\) 同理,\(d_j\) 表示第 \(j\) 维的 \(n\) 步后的位移量。相当对于 \([w_j-r_{i,j},w_j]\)\([1,-l_{i,j}]\) 这两段区间都不能选。对于第二轮,那么 \(l'_{i,j}\) 要么就是 \(l_{i,j}\),要么就是 \(l_{i,j}+d_j\)\(r_{i,j}\) 同理。发现每一轮位移量是相同的,那么对于经过 \(i\) 步,每一轮减少的方案数也是相同的,设 \(p_{i,j}=r'_{i,j}-r_{i,j}+l_{i,j}-l'_{i,j}\) 即经过 \(i\) 步第 \(j\) 维减少的方案数,\(g_j\) 表示第一轮后第 \(j\) 维的方案数。所以我们可以将统计答案改写成以下式子:

\[\sum_{i=1}^{n}\sum_{x=0}^{\infin}\prod_{j=1}^{k}(g_j-p_{i,j}-p_{n,j}x) \]

因为第 \(x+2\) 轮走了 \(i\) 步,第 \(2\sim x+1\) 轮每一轮第 \(j\) 维会减少 \(p_{n,j}\) 种方案,所以就是第 \(x+2\) 轮经过 \(i\) 步后的方案数。容易发现第二维上限是可以算出的,后面又是关于 \(x\)\(k\) 次多项式,所以可以在 \(k^2\) 的时间复杂度求出多项式系数,然后交换求和顺序变成求自然数幂和,即

\[\sum_{i=1}^{n}\sum_{j=0}^{k}h_j\sum_{x=0}^{\text{lim}}x^j \]

补充知识

复数

定义复数域 \(\mathbb{C}\),对于 \(z\in \mathbb{C}\)\(z\) 可以唯一表示为 \(a+b\mathrm{i}\),其中 \(a,b\in \R\),定义 \(\mathrm{i}^2=-1\)

基本运算法则:

  • \(z_1+z_2=(a_1+a_2)+(b_1+b_2)\mathrm{i}\)
  • \(z_1z_2=(a_1a_2-b_1b_2)+(a_1b_2+a_2b_1)\mathrm{i}\)
  • 如果 \(z_1=a+b\mathrm{i}\)\(z_2=a-b\mathrm{i}\),则 \(z_1\)\(z_2\) 互为共轭。

建立复平面,实轴为 \(x\),虚轴为 \(y\),则任意 \(z\) 在复平面上都可以表示成一个点坐标 \(Z(a,b)\)

考虑用向量表示 \(z\),即 \((\theta,r)\),其中 \(r=\lvert z\rvert=\sqrt{a^2+b^2}\),又称为 \(z\) 的模长。\(\theta\)\(\overrightarrow{OZ}\)\(x\) 正半轴的夹角。

简单推导可以得到 \(z=(\theta,r)=r(\cos\theta+\mathrm{i}\sin\theta)\),由欧拉公式 \(e^{\mathrm{i}\theta}=\cos \theta+\mathrm{i}\sin \theta\),可以得到 \(z=r\cdot e^{\mathrm{i}\theta}\)

于是可得:

  • \(z^n=r^n\cdot e^{\mathrm{i}n\theta}\)
  • \(\sqrt[n]{z}=\sqrt[n]{r}\cdot e^{\frac{\mathrm{i}(\theta+2k\pi)}{n}}\),其中 \(0\le k<n\)

单位根

定义 \(\omega_n\)\(n\) 次单位根,即 \(\omega_n^{n}=1\)

所以 \(\omega_n^n=1=e^{\mathrm{i}\cdot 0}\),于是 \(\omega_n=e^{\frac{\mathrm{i}2k\pi}{n}}\),为了方便,令 \(\omega_{n}=e^{\frac{\mathrm{i}2\pi}{n}}=\cos(\frac{2\pi}{n})+\mathrm{i}\sin(\frac{2\pi}{n})\)

那么 \(n\) 个根可以表示为 \(\omega^{0}_{n},\omega^{1}_{n},\cdots,\omega^{n-1}_{n}\)

对数

\(a^c=b\Longleftrightarrow \log_ab=c\)

\(\ln a=\log_ea\)

\(\log_{a}(bc)=\log_ab+\log_ac\)

\(\log_{a}(\frac{b}{c})=\log_ab-\log_ac\)

\(\log_{a}(b^n)=n\log_ab\)

\(\log_{a}b=\frac{\log_cb}{\log_ca}\)

极限

定义

\(f(x)\)\(x_0\) 的邻域有定义,若对于 \(\forall \varepsilon >0\)\(\exist \delta>0\),使得当 \(0<|x-x_0|<\delta\) 时,有 \(|f(x)-a|<\varepsilon\),则记 \(a=\lim\limits_{x\to x_0}f(x)\)

运算法则

\(\lim\limits_{x\to x_0}f(x)=a\)\(\lim\limits_{x\to x_0}g(x)=b\),则

  • \(\lim\limits_{x\to x_0}(f+g)(x)=a+b\)
  • \(\lim\limits_{x\to x_0}(fg)(x)=ab\)
  • 如果 \(b\ne 0\)\(\lim\limits_{x\to x_0}(\frac{f}{g})=\frac{a}{b}\)

如果 \(g(x)\)\(u\) 处有极限 \(a\)\(f(x)\)\(a\) 处有极限 \(b\),且存在 \((u-\delta,u)\cup (u,u+\delta)\) 使 \(g(x)\ne a\)。则

\[\lim\limits_{x\to u}(f\circ g)(x)=b \]

  • \(\lim[c\cdot f(x)]=c\cdot \lim f(x)\)
  • \(\lim[f(x)]^n=[\lim f(x)]^n\)

夹逼定理

\(g(x)\le f(x)\le h(x)\),且 \(\lim\limits_{x\to x_0}g(x)=\lim\limits_{x\to x_0}h(x)=a\),则 \(\lim\limits_{x\to x_0}f(x)=a\)

可证得重要结论

\[\lim\limits_{x\to 0}\frac{\sin x}{x}=1 \]

单调有界准则

设函数 \(f(x)\)\(x_0\) 的某左邻域单调且有界,则其左极限 \(\lim_{x\to x_0^{-}}f(x)\) 必定存在。

类似还有右极限和趋于无穷的单调有界准则。

可证得重要结论

\[e=\lim\limits_{x\to \infty}\left(1+\frac{1}{x}\right)^{x} \]

存在。

导数

定义

设函数 \(f(x)\)\(x_0\) 的某邻域 \(U(x_0)\) 内有定义,若极限

\[\lim_{x\to x_0}\frac{f(x)-f(x_0)}{x-x_0} \]

存在,则称 \(f(x)\)\(x_0\) 处可导,该极限为 \(f(x)\)\(x_0\) 处的导数,记为 \(f'(x_0)\)。也可改写为

\[f'(x_0)=\lim_{\Delta x\to 0}\frac{f(x_0+\Delta x)-f(x_0)}{\Delta x} \]


如果 \(f(x)\) 在区间 \(I\) 上处处可导,定义 \(f(x)\) 在区间上的导函数 \(f'(x)\)

\[f'(x)=\lim_{\Delta x\to 0}\frac{f(x+\Delta x)-f(x)}{\Delta x},x\in I \]

如果 \(y=f(x)\),那么 \(f'(x)=y'=\frac{dy}{dx}=\frac{d}{dx}f(x)\)

\(f(x)\)\(n\) 阶导记作 \(f^{(n)}(x)\)

运算法则

若函数 \(f(x)\)\(g(x)\) 可导,则

  • \((f+g)'=f'+g'\)
  • \((fg)'=f'g+fg'\)
  • 如果在 \(g\ne 0\) 处,\((\frac{f}{g})'=\frac{f'g-fg'}{g^2}\)

链式法则:若 \(u=g(x)\) 可导,\(v=f(u)\) 可导,则复合函数 \(f\circ g\) 可导,且 \((f\circ g)'(x)=f'(u)g'(x)=f'(g(x))g'(x)\)

指数对数化:指数和底数都含 \(x\) 的函数叫幂指函数,可通过指数对数化,\(f(x)^{g(x)}=e^{\ln f(x)^{g(x)}}=e^{g(x)\ln f(x)}\),然后通过链式法则和乘法法则求导。

常用结论

  • \(\frac{d}{dx}x^{n}=nx^{n-1}\),用定义加二项式定理可证明。

  • \(\frac{d}{dx}a^x=a^x\ln a\)

  • \(\frac{d}{dx}\log_a x=\frac{1}{x\ln a}\),特别地,\(\frac{d}{dx}\ln x=\frac{1}{x}\)

    • \(y=\log_a x\),则 \(a^{y}=x\)。同时对 \(x\) 求导得 \(a^{y}\ln a\cdot y'=1\),移项即得 \(y'=\frac{1}{x\ln a}\)

微分

定义

对于 \(y=f(x)\),如果当 \(\Delta x\to 0\) 时,\(\Delta y\) 可表示为 \(\Delta y=k\Delta x+o(\Delta x)\),其中 \(k\) 是常量,则称 \(f(x)\)\(x_0\) 处可微,\(dy=k\Delta x\),记为微分符号。

\(k=\lim\limits_{\Delta x\to 0}\frac{dy}{\Delta x}=\lim\limits_{\Delta x\to 0}\frac{k\Delta x+o(\Delta x)}{\Delta x}=\lim\limits_{\Delta x\to 0}\frac{\Delta y}{\Delta x}=f'(x_0)\)

定理

罗尔定理、拉格朗日中值定理、柯西中值定理。

洛必达法则

  • \(\lim\limits_{x\to a}f(x)=\lim\limits_{x\to a}F(x)=0\)
  • \(f(x)\)\(F(x)\)\(a\) 的某去心邻域可导且 \(F'(x)\ne 0\)
  • \(\lim\limits_{x\to a}\frac{f'(x)}{F'(x)}=A\)

\(\lim\limits_{x\to a}\frac{f(x)}{F(x)}=\lim\limits_{x\to a}\frac{f'(x)}{F'(x)}=A\)

以上是 \(0\)\(0\) 型,也有 \(\infty\)\(\infty\) 型。

泰勒中值定理

若函数 \(f(x)\) 在包含 \(x_0\) 在内的开区间 \((a,b)\)\((n+1)\) 阶可导,则对 \(\forall x\in(a,b)\)

\[f(x)=f(x_0)+\sum_{k=1}^{n}\frac{f^{(k)}(x_0)}{k!}(x-x_0)^k+R_n(x) \]

其中(\(\xi\)\(x\)\(x_0\) 之间的某个值)

\[R_n(x)=\frac{f^{(n+1)}(\xi)}{(n+1)!}(x-x_0)^{n+1} \]

上式称为 \(f(x)\)\(x_0\) 处展开的 \(n\) 阶泰勒公式,其中 \(R_n(x)\) 称为拉格朗日余项。

特别地,如果 \(f(x)\) 无穷阶可导,则它的无穷阶泰勒公式

\[\sum_{k=0}^{\infty}\frac{f^{(n)}(x_0)}{k!}(x-x_0)^k \]

称为它的泰勒级数。


在泰勒公式中,取 \(x_0=0\),得到麦克劳林公式

\[f(x)=f(0)+\sum_{k=1}^{n}\frac{f^{(k)}(0)}{k!}x^k+o(x^n) \]


常见函数的麦克劳林展开:

  • \(e^x=1+x+\frac{x^2}{2!}+\cdots+\frac{x^n}{n!}+\cdots\)
  • \(\sin x=x-\frac{x^3}{3!}+\frac{x^5}{5!}\cdots+(-1)^{n-1}\frac{x^{2n-1}}{(2n-1)!}+\cdots\)
  • \(\cos x=1-\frac{x^2}{2!}+\frac{x^4}{4!}+\cdots +(-1)^n\frac{x^{2n}}{(2n)!}\)+\(\cdots\)

积分

本质是求导的逆运算。

不定积分

\(F'(x)=f(x)\)\(d(F(x))=f(x)dx\),则 \(F(x)\)\(f(x)\) 的一个原函数。将 \(f(x)\) 的原函数集合(原函数加常数仍是原函数)称为它的不定积分,记

\[\int f(x)dx=F(x)+C \]

不定积分表(部分)

\[\int x^{a}dx=\frac{x^{a+1}}{a+1}+C(a\ne -1)\\ \int \frac{dx}{x}=\ln |x|+C \]

第一类换元积分法(凑微分)

\[\begin{aligned} \int f(x)dx&=\int g(\varphi(x))\varphi'(x)dx\\ &=\int g(u)\frac{du}{dx}dx\Big|_{u=\varphi(x)}\\ &=\int g(u)du\\ &=G(u)+C \end{aligned} \]

关键在于把 \(f(x)\) 凑成 \(g(u)u'\)

\[ \begin{aligned} \int 2xe^{x^2}dx&=\int u'e^{u}dx\Big|_{u=x^2}\\ &=\int e^udu\\ &=e^u+C\\ &=e^{x^{2}}+C \end{aligned} \]

第二类换元积分法

第一类反过来:

\[\begin{aligned} \int g(u)du&=\int g(\varphi(x))\varphi'(x)dx\Big|_{\varphi (x)=u}\\ &=\int f(x)dx\\ &=F(x)+C\\ &=F(\varphi^{-1}(u))+C \end{aligned} \]

例:

\[\begin{aligned} \int \sqrt{a^2-x^2}dx&=\int \sqrt{a^2-(a\sin t)^2}(a\sin t)'dt\Big|_{a\sin t=x}\\ &=\int \sqrt{a^2(1-\sin^2 t)}a\cos tdt\\ &=a^2\int \cos^2tdt\\ &=\frac{a^2}{2}\arcsin \frac{x}{a}+\frac{x}{2}\sqrt{a^2-x^2}+C \end{aligned} \]

还有三角代换、倒代换。

分部积分法

\((uv)'=u'v+uv'\)

\[\int uv'dx=uv-\int u'vdx \]

可简写为

\[\int udv=uv-\int vdu \]

\(u\) 的选取遵循“反对幂指三”。

定积分

\[\int_a^bf(x)dx=\lim_{\Delta x_i\to 0}\sum_{i=1}^{n}f(\xi_i)\Delta x_i \]

可以看作 \([a,b]\) 区间围成图形的面积。

可以求弧长、体积、侧面积,在 OI 中可用来估计时间复杂度。

牛顿-莱布尼茨公式

微积分基本定理。

\[\int_a^b f(x)dx=F(x)\Big|_{b}^{a}=F(b)-F(a) \]

其中 \(F(x)\)\(f(x)\)\([a,b]\) 上的原函数。

斯特林公式

\(n!\sim \sqrt{2\pi n}(\frac{n}{e})^n\),可以用来估计时间复杂度。

数值积分

用于求定积分的近似值。

辛普森公式:

\[\int_a^bf(x)dx\approx \frac{b-a}{b}\left(f(a)+4f(\frac{a+b}{2})+f(b)\right) \]

以及自适应辛普森算法。

快速傅里叶变换

FFT

对于多项式 \(F(x)=\sum\limits_{i=0}^{n-1}a_ix^{i}\)\(G(x)=\sum\limits_{i=0}^{m-1}b_ix^{i}\),求 \(H=F*G\)

\(H=\sum\limits_{i=0}^{n+m-2}c_ix^i\),由于这是关于 \(x\)\(n+m-2\) 次函数。朴素的话有 \(c_i=\sum\limits_{j=0}^{i}a_jb_{i-j}\)

考虑快速求出 \(H\)\(n+m-1\) 个点值,再快速求出 \(H\)

DFT

因为 \(H(x)=F(x)\cdot G(x)\),考虑选出 \(N=n+m-1\) 个点 \(x_0,\cdots,x_{N-1}\),考虑 \(F\),有

\[\begin{bmatrix} x_0^{0} & x_0^{1} & \cdots & x_{0}^{N-1} \\ x_1^{0} & x_1^{1} & \cdots & x_{1}^{N-1} \\ \vdots & \vdots & \ddots & \vdots \\ x_{N-1}^{0} & x_{N-1}^{1} & \cdots & x_{N-1}^{N-1} \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ \vdots \\ a_{N-1} \end{bmatrix}= \begin{bmatrix} F(x_0) \\ F(x_1) \\ \vdots \\ F(x_{N-1}) \end{bmatrix} \]

直接算时间复杂度是 \(O(N^2)\) 的,考虑递归的思想。

通过神奇的观察可以发现,当 \(x_i=\omega_{N}^i\) 时,左边矩阵不同的数只有 \(N\) 个,接下来就好办了。

\(x=\omega_n^{i}\)。定义 \(F_0(x)\)\(F_1(x)\)

\[F(x)=a_0x^0+a_1x^1+a_2x^2+a_3x^3+\cdots+a_{n-2}x^{n-2}+a_{n-1}x^{n-1}\\ F_0(x)=a_0x^0+a_2x^1+\cdots+a_{n-2}x^{\frac{n-2}{2}}\\ F_1(x)=a_1x^0+a_3x^1+\cdots+a_{n-1}x^{\frac{n-2}{2}} \]

于是有 \(F(x)=F_0(x^2)+xF_1(x^2)\)。令 \(m=\frac{n}{2}\),容易发现 \((\omega_{n}^{i})^2=\omega_{m}^{i}\),所以发现变成子任务,然后分类讨论:

  • \(0\le i<m\)\(F(\omega_{n}^{i})=F_0(\omega_{m}^i)+\omega_{n}^{i}F_1(\omega_{m}^{i})\)
  • \(0\le i<m\)\(F(\omega_{n}^{i+m})=F(-\omega_{n}^{i})=F_0(\omega_{m}^{i})-\omega_{n}^{i}F_1(w_{m}^{i})\)

\(F_0\)\(F_1\) 都可以递归算,所以时间复杂度为 \(O(n\log n)\),为了方便常把 \(N\) 补成 \(2\) 的幂次。

IDFT

已知左边矩阵和答案矩阵求系数矩阵,容易发现即求左边矩阵的逆矩阵。

经过观察可以发现,令左边矩阵为 \(X\)\(X_{i,j}=\omega_{N}^{ij}\),则 \(X^{-1}_{i,j}=\frac{1}{N}\omega_{N}^{-ij}\)。通过直接计算可以证明。

实现细节

  • 可以手写复数类,容易发现 \(\omega_{N}^{i}\)\(\omega_{N}^{-i}\) 互为共轭,所以 DFT 和 IDFT 可以调用一个函数,传一个参进去即可。

  • 可以去掉递归,只需要求出每个位置 \(i\) 在底层时对应哪个位置 \(i'\) 即可,通过观察可以发现 \(i'\) 事实上是 \(i\) 的二进制翻转。然后模拟递归过程,从底层开始,每次合并 \(2^{k}\) 个数。

  • 对于 \(F_0\)\(F_1\),将 \(F_0(\omega_{m}^{i})\) 的值存在 \(i\) 的位置,\(F_1(\omega_{m}^{i})\) 的值存在 \(m+i\) 的位置,这样就不用新开空间了。

  • 求单位根。如果已知 \(0\sim m-1\)\(\omega_{m}^{i}\),那么可以直接算出 \(\omega_{n}^{i}\),对于 \(i\equiv 0\pmod 2\)\(\omega_{n}^{i}=\omega_{m}^{i/2}\),否则只需要先通过欧拉公式求出 \(\omega_{n}\),则 \(\omega_{n}^{i}=\omega_{n}^{i-1}\omega_n\)

void fft(comp a[],int n,int ty){
	for(int i=0,j=0;i<n;i++){
		if(i<j)swap(a[i],a[j]);
		for(int k=n>>1;(j^=k)<k;k>>=1);
	}
	w[0]=comp{1,0};
	for(int i=1;i<n;i<<=1){
		int t=i*2;
		comp x=comp{cos(2*pi/t),ty*sin(2*pi/t)};
		for(int j=t-2;j>=0;j-=2)w[j]=w[j>>1],w[j+1]=w[j]*x;
		for(int j=0;j<n;j+=t){
			for(int k=j;k<j+i;k++){
				comp t0=a[k],t1=a[k+i]*w[k-j];
				a[k]=t0+t1;
				a[k+i]=t0-t1;
			}
		}
	}
	if(ty==-1){
		for(int i=0;i<n;i++)a[i].a/=n,a[i].b/=n;
	}
}

例题

01序列问题

给出两个长度分别为 \(n\)\(m\) 的 01 序列 \(A\)\(B\),有 \(Q\) 次询问,每次询问当把 \(A\) 的第 \(i\) 位和 \(B\) 的第 \(j\) 位对齐时,\(A\),\(B\) 公共部分有多少对对齐且相同的数。


不如将 \(B\) 序列翻转得到 \(B'\),则 \(A\times B'\)\(i\) 次项就是 \(\sum\limits_{j=0}^{i}A_{j}B'_{i-j}\),即将 \(A\)\(B\) 的第 \(m-i\) 位对齐都是 \(1\) 的位置数。

然后分别将 01 取反再跑一次就得到都是 \(0\) 的位置数。

[HNOI2017] 礼物

如果将 \(A\) 序列加 \(x\)(这里允许 \(x\) 为负数,相当于 \(B\) 序列加 \(-x\)),则答案为

\[\sum_{i=0}^{n-1}(A_i+x-B_i)^2=S^2(A)+S^2(B)+2x(S(A)-S(B))+nx^2-2\sum_{i=0}^{n-1}A_iB_i \]

容易发现前 \(2\) 项为定值,中间 \(2\) 项可以通过枚举 \(x\) 算,只需要考虑求最后一项的最大值。

\(B\) 翻转并复制一份即可。

快速数论变换

NTT

对于 FFT,只能处理 \(10^4\times 10^4\times 10^6\) 级别问题,其中 \(10^4\) 是值域,\(10^6\) 是长度。否则会爆 double。

如果题目中有模数且可以用 NTT,则能处理 \(p\times p\times 10^6\) 级别问题。并且将复数运算代替为取模运算,常数更加优秀。


考虑在模意义下的多项式乘法,如果模数 \(p\) 有原根,那么本质上原根和单位根是相同的。\(g^{0,1,\cdots,p-2}\) 相当于 \(\omega_{p-1}^{0,1,\cdots,p-2}\),都是互不相同且能达到效果的。并且易得 \(\omega_{n}=g^{\frac{p-1}{n}}\),因为 \(n\) 次方均为 \(1\)。也就是说当 \(n\mid p-1\) 时,单位根才存在。

而在 DFT 和 IDFT 的过程中,要求长度是 \(2\) 的幂次,也就是说要满足 \(2^k\mid p-1\),这也就限制了一些模数不可取。

常见的模数有

  • \(998244353=7\times 17\times 2^{23}+1\),原根为 \(3\),能处理长度 \(\le 2^{23}\)
  • \(1004535809=479\times 2^{21}+1\),原根为 \(3\)
  • \(469762049 = 7\times 2^{26}+1\),原根为 \(3\)

在 IDFT 时,要求 \(\omega_n^{-i}\),本质就是 \(g^{-\frac{p-1}{n}}=(g^{-1})^{\frac{p-1}{n}}\)

void ntt(int a[],int n,int ty){
	for(int i=0,j=0;i<n;i++){
		if(i<j)swap(a[i],a[j]);
		for(int k=n>>1;(j^=k)<k;k>>=1);
	}
	g[0]=1;
	for(int i=1;i<n;i<<=1){
		int t=i*2;
		int x=ksm(ty==1?3:(P+1)/3,(P-1)/t);
		for(int j=t-2;j>=0;j-=2)g[j]=g[j>>1],g[j+1]=(ll)g[j]*x%P;
		for(int j=0;j<n;j+=t){
			for(int k=j;k<j+i;k++){
				int t0=a[k],t1=(ll)a[k+i]*g[k-j]%P;
				a[k]=mod(t0+t1);
				a[k+i]=mod(t0+P-t1);
			}
		}
	}
	if(ty==-1){
		int x=ksm(n,P-2);
		for(int i=0;i<n;i++)a[i]=(ll)a[i]*x%P;
	}
}

差卷积

在一些题目当中会出现 \(c_i=\sum\limits_{j=i}^{n}a_{j}b_{j-i}\) 的形式,因为 \(j-(j-i)=i\),所以叫做差卷积。

只需

\[\begin{aligned} c_i&=\sum_{j=i}^{n}a_jb_{j-i}\\ &=\sum_{j=0}^{n-i}a_{i+j}b_{j}\\ &=\sum_{j=0}^{n-i}a'_{n-i-j}b_{j} \end{aligned} \]

其中 \(a'\)\(a\) 的翻转。发现相当于求 \(a'\)\(b\) 的和卷积的第 \(n-i\) 项。

任意模数卷积

值域 \(\le 10^9\)\(n\le 10^5\)

9 NTT

因为不保证模数是 NTT 模数,所以不能直接 NTT。

考虑到最后答案 \(\le 10^{23}\),所以可以三模 NTT。即取三个 NTT 模数分别得出结果,然后 crt 即可求出真实答案,再进行对模数取模。

8 FFT

因为答案太大,会爆 double,考虑拆位。

\(x\) 拆成 \(\lfloor\frac{x}{s}\rfloor s+x\bmod s\),其中 \(s=\sqrt{10^9}\)。然后 \(A_1\) 存前半部分,\(A_2\) 存后半部分,那么 \(A*B=(A_1s+A_2)*(B_1s+B_2)=A_1*B_1s^2+(A_1*B_2+A_2*B_1)s+A_2*B_2\)

这样卷积答案就只有 \(10^{14}\) 量级,但是总共要跑 \(8\) 次 FFT。

5 FFT

考虑构造复数多项式 \(F=A_1+A_2\mathrm{i}\)\(G=A_1-A_2\mathrm{i}\)\(H=B_1+B_2\mathrm{i}\)。发现通过算出 \(F*H\)\(G*H\) 可以解出 \(8\) FFT 需要的值。总共只有 \(5\) 次 FFT。

\(O(\text{5 FFT})<O(\text{9 NTT})\)

4 FFT 去哪了呢?

快速沃尔什变换

解决 \(c_i=\sum\limits_{j\oplus k=i}a_jb_k\),其中 \(\oplus\) 是一个位运算,如 \(\mathbf{xor}\)\(\mathbf{or}\)\(\mathbf{and}\)

思想

异或卷积

考虑构造线性变换 \(\mathcal{T}\) 使得 \(\mathcal{T}(F)_i\cdot \mathcal{T}(G)_i=\mathcal{T}(H)_i\)。相当于对于一个向量乘以矩阵 \(M\) 得到一个新的向量。可以这样写

\[\left(\sum_{j=0}^{n-1}a_jM_{j,i}\right)\left(\sum_{j=0}^{n-1}b_{j}M_{j,i}\right)=\sum_{j=0}^{n-1}c_jM_{j,i} \]

可以变形得到

\[\begin{aligned} \sum_{j=0}^{n-1}\sum_{k=0}^{n-1}a_jb_kM_{j,i}M_{k,i}&=\sum_{j=0}^{n-1}\sum_{k\ \mathbf{xor}\ l=j}a_{k}b_{l}M_{j,i}\\ &=\sum_{j=0}^{n-1}\sum_{k=0}^{n-1}a_jb_kM_{j\ \mathbf{xor}\ k,i} \end{aligned} \]

于是可以得到 \(M_{j,i}M_{k,i}=M_{j\ \mathbf{xor}\ k,i}\)。然后经过一顿推导,发现

\[F_i(k)=F_{i-1}(k)+F_{i-1}(k+2^{i-1})\\ F_i(k+2^{i-1})=F_{i-1}(k)-F_{i-1}(k+2^{i-1}) \]

然后就可以 \(O(n\log n)\) 算了。逆变换相当于解二元一次方程,最后除以 \(n\) 即可。

void fwt(int a[],int n,int ty){
	for(int i=1;i<n;i<<=1){
		int t=i*2;
		for(int j=0;j<n;j+=t){
			for(int k=j;k<j+i;k++){
				int t0=a[k],t1=a[k+i];
				a[k]=mod(t0+t1);
				a[k+i]=mod(t0+p-t1);
			}
		}
	}
	if(ty==-1){
		int x=ksm(n,p-2);
		for(int i=0;i<n;i++)a[i]=(ll)a[i]*x%p;
	}
}

或卷积

同理可以得到 \(M_{j,i}M_{k,i}=M_{j\ \mathbf{and}\ k,i}\),构造 \(M_{x,y}=[x\subseteq y]\) 满足条件。

那么 \(\mathcal{T}(F)_i=\sum\limits_{j\subseteq i}a_j\),相当于做高维前缀和,有

\[F_i(k)=F_{i-1}(k)\\ F_i(k+2^{i-1})=F_{i-1}(k)+F_{i-1}(k+2^{i-1}) \]

逆变换易得。时间复杂度 \(O(n\log n)\)

void fwt(int a[],int n,int ty){
	for(int i=1;i<n;i<<=1){
		int t=i*2;
		for(int j=0;j<n;j+=t){
			for(int k=j;k<j+i;k++){
				a[k+i]=mod(a[k]*ty+a[k+i]);
			}
		}
	}
}

与卷积

对于与卷积,与或卷积类似,构造 \(M_{x,y}=[y\subseteq x]\) 满足条件。然后即做高维后缀和,有

\[F_i(k)=F_{i-1}(k)+F_{i-1}(k+2^{i-1})\\ F_i(k+2^{i-1})=F_{i-1}(k+2^{i-1}) \]

代码与或卷积类似。

子集卷积

\[h(i)=\sum_{j\subseteq i}f(j)g(i\ \mathbf{xor}\ j) \]

等价于

\[h(i)=\sum_{j\ \mathbf{or}\ k=i,|j|+|k|=|i|}f(j)g(k) \]

其中 \(|x|\) 表示 \(\text{popcount}(x)\)

把长度看成 \(2^n\)。如果只有第一个条件我们可以 \(O(2^n n)\) 求出,考虑增加第二个条件。

发现有点类似和卷积的形式,新开一维状态表示 \(1\) 的个数,有

\[h_w(i)=\sum_{j\ \mathbf{or}\ k=i}\sum_{t=0}^{n}f_t(j)g_{w-t}(k) \]

于是我们便可以枚举 \(w=0\sim n\) 求出 \(\mathcal{T}(F_{w})\)\(\mathcal{T}(G_{w})\),然后用 \(O(2^{n}n^2)\) 的时间复杂度合并,然后再每一位逆变换回去即可。总体时间复杂度 \(O(2^nn^2)\)

常见用于优化状压 dp。

多项式全家桶

https://www.luogu.com.cn/paste/1kz4jufv

多项式求逆

已知 \(A(x)\),求 \(B(x)\) 使 \(A(x)B(x)\equiv 1\pmod {x^n}\)

取模是因为 \(B\) 可能有无限多项,故只取前 \(n\) 项。\(O(n^2)\) 暴力是容易的,直接递推即可;考虑用倍增优化。

假设已经求出 \(B\) 的前 \(m\) 项,记为 \(B_m\),考虑求出 \(B_{2m}\)。我们可以得到到两个式子:

\[A(x)B_{2m}(x)\equiv 1\pmod {x^{2m}}\\ B_{2m}(x)-B_{m}(x)\equiv 0\pmod {x^{m}} \]

将第二个式子平方可得

\[B_{2m}(x)^2-2B_{2m}(x)B_m(x)+B_m(x)^2\equiv 0\pmod {x^{2m}} \]

再同时乘上 \(A(x)\),由第一个式子得

\[B_{2m}(x)-2B_{m}(x)+B_m(x)^2A(x)\equiv 0\pmod{x^{2m}} \]

通过移项可得

\[B_{2m}(x)\equiv 2B_m(x)-A(x)B_m(x)^2\pmod{x^{2m}} \]

每次计算时 \(A\) 只取前 \(2m\) 项,那么时间复杂度为 \(\sum\limits_{i=1}^{\log_2 n}i2^i=n\log n\)

多项式除法

已知 \(A(x)\)\(B(x)\),求 \(D(x)\)\(R(x)\) 使得

\[A(x)=B(x)D(x)+R(x) \]

假设 \(A(x)\)\(n\) 次,\(B(x)\)\(m\) 次,则要求 \(R(x)\) 低于 \(m\) 次。\(D(x)\) 显然是 \(n-m\) 次,令 \(R(x)\)\(m-1\) 次(高位如果不存在用 \(0\) 补位)。

考虑将系数翻转,即 \(A'(x)=A(x^{-1})x^n\),因为

\[A(x^{-1})=B(x^{-1})D(x^{-1})+R(x^{-1}) \]

所以

\[A(x^{-1})x^n=B(x^{-1})x^{m}D(x^{-1})x^{n-m}+R(x^{-1})x^n\\ A'(x)=B'(x)D'(x)+R'(x)x^{n-m+1} \]

可以得到

\[A'(x)\equiv B'(x)D'(x)\pmod {x^{n-m+1}} \]

于是可以算出 \(D'(x)\),且是 \(n-m\) 次的,符合要求。

然后 \(R(x)=A(x)-B(x)D(x)\)。总时间复杂度 \(O(n\log n)\)

线性递推

已知 \(f_0\sim f_{m-1}\)\(d_{0}\sim d_{m-1}\),且

\[f_{n}=\sum_{i=0}^{m-1}f_{n-i-1}d_i \]

\(f_{n}\)

通过矩阵快速幂可以做到 \(O(m^3\log n)\),考虑优化。

有特征方程 \(x^{m}=\sum\limits_{i=0}^{m-1}x^{m-i-1}d_i\)。任何 \(f_{n}\) 都可以用 \(f_{0\sim m-1}\) 表示,所以只需求出 \(x^{n}\)

考虑倍增,已知 \(x^{k}\),如何求出 \(x^{2k}\)

\[x^{k}=\sum_{i=0}^{m-1}a_ix^{i} \]

将两边同时平方,需要将 \(x^{m\sim 2m-2}\) 的项进行降幂处理。事实上,这个操作等价于将它对 \((x^{m}-\sum\limits_{i=0}^{m-1}x^{m-i-1}d_i)\) 取模,因为该式结果为 \(0\),而降幂本质上是不断减去这个多项式乘以一个整式,而结果不变,所以是等价的。

取模用多项式除法即可,于是总时间复杂度为 \(O(m\log m\log n)\)

多项式多点求值

已知 \(F(x)\),求 \(F(x_{1\sim m})\)

先考虑在 \(m\) 较小的情况下,想到构造 \(G(x)\) 使得 \(G(x_i)=F(x_i)\),且 \(G(x)\) 的次数不超过 \(m\) 次。

仿照线性递推降幂的思路,由于

\[A(x)=\prod_{i=1}^{m}(x-x_i) \]

对于 \(x=x_i\) 结果为 \(0\),且次数为 \(m\),所以将 \(F(x)\)\(A(x)\) 取模后便能得到 \(G(x)\)。时间复杂度瓶颈在带值 \(O(m^2)\)

考虑进行分治。令 \(A_{l,r}(x)\)\(\prod\limits_{i=l}^{r}(x-x_i)\),那么将 \(F(x)\) 从上至下一直取模到 \(A_{i,i}(x)\),容易发现此时的 \(F(x)\) 就是 \(F(x_i)\),因为 \(F(x)\) 只剩常数项,且取模不改变 \(F(x_i)\) 的值。时间复杂度为 \(O(n\log^2 n)\)

转置原理优化

https://www.luogu.com.cn/article/5l5gpirn

多项式开方

已知 \(A(x)\),求 \(B(x)^2\equiv A(x)\pmod {x^{n}}\)

暴力可以 \(O(n^2)\) 做,仿照求逆的思路,考虑倍增。

假设已知 \(B_m(x)\),求 \(B_{2m}(x)\)。可以得到

\[B_{2m}(x)-B_{m}(x)\equiv 0\pmod {x^{m}}\\ B_{2m}(x)^2-2B_{2m}(x)B_{m}(x)+B_m(x)^2\equiv 0\pmod {x^{2m}}\\ \]

因为

\[B_{2m}(x)^2\equiv A(x)\pmod{x^{2m}} \]

所以

\[B_{2m}(x)\equiv\frac{A(x)+B_{m}(x)^2}{2B_{m}(x)}\pmod {x^{2m}} \]

多项式求导/积分

\(F(x)=\sum\limits_{i=0}^{n}a_ix^i\),根据求导和积分法则可以得到

\[F'(x)=\frac{d}{dx}F(x)=\sum_{i=0}^{n-1}a_{i+1}(i+1)x^i\\ \int F(x)dx=\sum_{i=1}^{n+1}\frac{a_{i-1}}{i}x^i \]

时间复杂度显然为 \(O(n)\)

多项式 ln(exp)

已知 \(A(x)\),求 \(B(x)=\ln A(x)\),即 \(e^{B(x)}=A(x)\)

\(B(x)\) 存在的条件为 \([x^0]A(x)=1\),否则找不到 \(e^k\equiv [x^0]A(x)\pmod p\)

考虑先对 \(\ln A(x)\) 求导,然后再积分回去

\[\frac{d}{dx}\ln A(x)=\frac{d}{dA(x)}\ln A(x)\frac{d}{dx}A(x)=\frac{A'(x)}{A(x)}\\ \ln A(x)=\int\frac{A'(x)}{A(x)}dx \]

总时间复杂度为 \(O(n\log n)\)


已知 \(A(x)\),求 \(B(x)=e^{A(x)}\)

\(B(x)\) 存在的条件为 \([x^0]A(x)=0\)

求解可以通过牛顿迭代。

牛顿迭代指的是,已知 \(G(x)\),求 \(F(x)\) 使得 \(G(F(x))\equiv 0\pmod {x^n}\)

比如说想求 \(B(x)\equiv \sqrt {A(x)}\pmod {x^n}\),则构造 \(G(B(x))=A(x)-B^2(x)\),考虑如何求解。

考虑倍增,已知 \(B_m(x)\),如何求 \(B_{2m}(x)\)

我们让 \(G(B_{2m}(x))\)\(B_{m}(x)\) 处泰勒展开

\[G(B_{2m}(x))=\sum_{i=0}^{\infty}\frac{G^{(i)}(B_{m}(x))}{i!}(B_{2m}(x)-B_m(x))^i\equiv 0\pmod {x^{2m}} \]

容易发现 \(B_{2m}(x)-B_m(x)\) 的最低次至少 \(x^{m}\),所以当 \(i\ge 2\) 时在 \(\bmod x^{2m}\) 后都变成 \(0\) 了,所以又可以写成

\[G(B_{2m}(x))\equiv G(B_{m}(x))+G'(B_{m}(x))(B_{2m}(x)-B_{m}(x))\pmod {x^{2m}} \]

然后便得到

\[B_{2m}(x)\equiv B_{m}(x)-\frac{G(B_m(x))}{G'(B_m(x))}\pmod {x^{2m}} \]

回归本题,只需构造 \(G(B(x))=A(x)-\ln B(x)\) 即可。注意 \(G\) 求导是关于 \(B_m(x)\),所以 \(A(x)\) 是常量。

\[B_{2m}(x)\equiv B_{m}(x)-\frac{A(x)-\ln B_{m}(x)}{-\frac{1}{B_m(x)}}\equiv B_m(x)(1-\ln B_m(x) +A(x))\pmod {x^{2m}} \]

时间复杂度 \(O(n\log n)\)

多项式快速幂

已知 \(A(x)\),求 \(B(x)=A^k(x)\bmod x^{n}\)

考虑两边取对数,得 \(\ln B(x)=k\ln A(x)\),算出 \(\ln B(x)\) 后再 \(\exp\) 回去,接下来讨论两个问题:

  • \(k\) 应该对 \(p\) 取模。考虑 \(e^{x}\) 的泰勒展开,将 \(x\) 替换为 \(k\ln A(x)\),发现 \(x\) 并不在指数位,所以可以直接取模。
  • \([x^0]A(x)\ne 1\)。显然不能直接求 \(\ln\),找到 \(A(x)\) 的最低次有效项 \(a_ix^i\),所以

    \[\begin{aligned} B(x)&=\left(a_ix^i\frac{A(x)}{a_ix^i}\right)^k\\ &=a_i^kx^{ik}\exp\left(k\ln \frac{A(x)}{a_ix^i}\right) \end{aligned} \]

    因为对 \(x^{n}\) 取模,所以若 \(ik\) 太大则结果为全 \(0\) 多项式。

快速拉格朗日插值

我们要求

\[f(x)=\sum_{i=0}^ny_i\prod_{j=0,j\ne i}^n\frac{x-x_j}{x_i-x_j} \]

观察到分母和 \(i,j\) 都有关,尝试拿出来单独求

\[g_i(x)=\prod_{j\ne i}(x-x_j) \]

容易发现对于 \(k\ne i\)\(g_k(x_i)=0\),所以可以把所有的 \(g_i(x)\) 加起来,不影响 \(g_i(x_i)\) 的值。

\[G(x)=\sum_{i=1}^{n}\prod_{j\ne i}\left(x-x_j\right) \]

这里已经可以直接分治 NTT 求了,但是常数较大,注意到

\[H(x)=\prod_{i=1}^{n}(x-x_i)\\ \begin{aligned} H'(x)&=\sum_{i=1}^{n}(x-x_i)'\prod_{j\ne i}(x-x_j)\\ &=\sum_{i=1}^{n}\prod_{j\ne i}(x-x_j)\\ &=G(x) \end{aligned} \]

所以只需要分治 NTT 求出 \(H(x)\) 后求导即得 \(G(x)\),然后用多项式多点求值求出 \(G(x_{1\sim n})\)

现在即求

\[f(x)=\sum_{i=0}^{n}\frac{y_i}{G(x_i)}\prod_{j\ne i}(x-x_j) \]

直接上分治 NTT,有

\[f_{i,i}(x)=\frac{y_i}{G(x_i)}\\ f_{l,r}(x)=f_{l,mid}(x)H_{mid+1,r}+f_{mid+1,r}(x)H_{l,mid} \]

总时间复杂度 \(O(n\log ^2 n)\)

生成函数

解决无标号计数问题常用普通生成函数,有标号计数问题则是指数生成函数。

普通生成函数

对于数列 \(a\),定义其普通生成函数(OGF)为

\[F(x)=\sum_{n\ge 0}a_nx^{n} \]

容易发现 \(F(x)G(x)\) 为数列 \(\sum_{i=0}^{n}a_ib_{n-i}\) 的 OGF。

常见封闭形式有:

  • 等比数列

    \[\sum_{n\ge 0}p^nx^n=\frac{1}{1-px} \]

  • 组合数列

    \[\sum_{n\ge 0}\binom{m+n-1}{n-1}=\frac{1}{(1-x)^m}=\left(\sum_{n\ge 0}x^n\right)^{m} \]

    可用隔板法证明。

  • 等差幂数列

    \[\sum_{n\ge 0}x^{nk}=\frac{1}{1-x^k} \]

将形式幂级数转换为封闭形式的作用是方便乘除。

指数生成函数

对于数列 \(a\),定义其指数生成函数(EGF)为

\[\hat{F}(x)=\sum_{n\ge 0}a_n\frac{x^n}{n!} \]

容易发现 \(\hat{F}(x)\hat{G}(x)\) 为数列 \(\sum_{i=0}^{n}\binom{n}{i}a_ib_{n-i}\) 的 EGF。有组合意义。

注意到

\[\hat{F}(x)=\sum_{n\ge 0}\frac{x^n}{n!}=e^x \]

因为 \(e^x\) 的麦克劳林展开为它。

EGF 与 EXP 的组合意义

\(\hat{F}(x)\)\(f(x)\) 的 EGF。

如果 \(\exp \hat{F}(x)=\hat{G}(x)\),则 \(\hat{G}(x)\)

\[g_n=\sum_{[n]=\{S_1,S_2,\cdots,S_k\}}\prod_{i=1}^{k}f_{|S_i|} \]

或者说

\[g_n=\sum_{i=1}^{n}\binom{n-1}{i-1}f_ig_{n-i} \]

的 EGF。


代数角度推导:

\[g_n=\sum_{i=1}^{n}\binom{n-1}{i-1}f_ig_{n-i}\\ \frac{g_n}{(n-1)!}=\sum_{i=1}^{n}\frac{f_i}{(i-1)!}\frac{g_{n-i}}{(n-i)!}\\ \hat{G}'(x)x=\hat{F}'(x)\hat{G}(x)x\\ \hat{F}(x)=\int \frac{\hat{G}'(x)}{\hat{G}(x)}dx=\ln \hat{G}(x) \]


\(n\) 个点的简单有标号无向连通图数量。以下均是有标号的前提下。

\(f(i)\)\(i\) 个点的简单无向连通图数量,\(g(i)\)\(i\) 个点的简单无向图数量。所以 \(g(i)=2^{\binom{i}{2}}\),即看每条边选不选。令 \(\hat{F}(x)\)\(\hat{G}(x)\) 分别为它们的指数生成函数。

看上面两个式子,\(g(i)\) 显然可以拆分成若干个连通块,所以符合第一个式子;然后考虑暴力,枚举一个连通块,其他的点随便连。但是为了避免算重,固定枚举 \(1\) 号点所在连通块的大小,并在剩下 \(n-1\) 个点中选出在连通块内的点,于是便能得到第二个式子。通过第二个式子便能在 \(O(n^2)\) 的时间复杂度内求得 \(f(n)\)

如果用上面的结论,就有 \(\exp \hat{F}(x)=\hat{G}(x)\),如果是对的就能直接通过取 \(\ln\) 算出 \(F(x)\),考虑一下它的组合意义

\[\exp \hat{F}(x)=\sum_{i=0}^{\infty}\frac{\hat{F}(x)^i}{i!} \]

考虑 \([x^k]\)。分子表示的是 \(k\) 个点包含 \(i\) 个有序连通块的方案数,那么除以 \(i!\) 即表示 \(k\) 个点包含 \(i\) 个无序连通块的方案数,那么相加起来即表示 \(k\) 个点包含若干无序连通块的方案数,也就正好是 \([x^k]\hat{G}(x)\)。所以就能对应上。

应用

\(m\) 种物品,体积为 \(a_i\),数量为 \(b_i\),对 \(1\sim n\) 求填满容积为 \(x\) 背包的方案数。

\(f(i)\) 为容积为 \(i\) 的方案数,\(F(x)\) 为它的普通生成函数。容易发现

\[\begin{aligned} F(x)&=\prod_{i=1}^{m}\left(1+x^{a_i}+x^{2a_i}+\cdots+x^{a_ib_i}\right)\\ &=\prod_{i=1}^{m}\frac{1-x^{a_i(b_i+1)}}{1-x^{a_i}} \end{aligned} \]

要求 \(F(x)\),考虑两边取 \(\ln\)

\[\ln F(x)=\sum_{i=1}^{m}\ln(1-x^{a_i(b_i+1)})-\ln(1-x^{a_i}) \]

考虑如何求 \(\ln (1-x^{k})\),可以求导后积分回去,即

\[\begin{aligned} \int \frac{-kx^{k-1}}{1-x^{k}} dx&=\int (-kx^{k-1})(1+x^k+x^{2k}+\cdots)dx\\ &=\int -k(x^{k-1}+x^{2k-1}+\cdots)dx\\ &=-\sum_{j=1}^{\infty}\frac{x^{kj}}{j} \end{aligned} \]

所以

\[\ln F(x)=\sum_{i=1}^{m}\sum_{j=1}^{\infty}\frac{-x^{a_i(b_i+1)j}+x^{a_ij}}{j} \]

我们只关心 \([x^k]F(x)(k\le n)\),所以如果枚举 \(i\) ,枚举量是 \(O(n\log n)\) 级别的,求出系数后再 \(\exp\) 回去即可。总时间复杂度 \(O(n\log n)\)


有集合 \(S\),已知 \(f(1\sim n)\)\(i\) 表示成 \(S\) 中元素之和的方案数,求 \(S\)

仿照上题,\(s_k=[k\in S]\),有

\[\ln F(x)=-\sum_{k=1}^{\infty}s_k\ln (1-x^k) \]

写成

\[\sum_{i=1}^{n}f(i)x^i=\sum_{k=1}^{\infty}\sum_{i=1}^{\infty}\frac{x^{ik}}{i}s_k \]

每次比较 \(x_i\) 的系数然后更新即可。


已知 \(a_{1\sim m}\)\(f(k)=\sum a_i^k\),求 \(f(1\sim n)\)

\(s_k=\sum_{i=1}^{m}[a_i=k]\)

\[\begin{aligned} F(x)&=\sum_{n=0}^{\infty}\sum_{i=1}^{m}(a_i x)^n\\ &=\sum_{i=1}^{m}\frac{1}{1-a_ix} \end{aligned} \]

分式相加不太好处理,考虑同时积分

\[\begin{aligned} \int F(x)dx&=\sum_{i=1}^{m}\int \frac{1}{1-a_ix}dx\\ &=\sum_{i=1}^{m}-\frac{1}{a_i}\ln(1-a_ix) \end{aligned} \]

有个 \(\frac{1}{a_i}\) 不太好搞,考虑把 \(F(x)\) 写为

\[\sum_{i=1}^{m}\left(\frac{a_ix}{1-a_ix}+1\right)=m+x\sum_{i=1}^{m}\frac{a_i}{1-a_ix} \]

然后就变成

\[\sum_{i=1}^{m}-\ln(1-a_ix)=-\ln\left(\prod_{i=1}^{m}(1-a_ix)\right) \]

然后分治 NTT 即可。

posted @ 2025-04-16 20:49  _chara  阅读(92)  评论(10)    收藏  举报
Title