浅谈多项式

1.FFT/NTT

略。

2.多项式求逆

\(F^{-1}(x)\times F(x)=1\pmod {x^n}\)

我们假设已经求出了 \(F_*^{-1}(x)\times F(x)=1\pmod {x^{n/2}}\)\(n/2\) 向上取整)
\(F^{-1}(x)\times F(x)=1\pmod {x^{n/2}}\)
\(F_*^{-1}(x)-F^{-1}(x)=0\pmod {x^{n/2}}\)
\(F_*^{-2}(x)+F^{-2}(x)-2F_*^{-1}(x)F^{-1}(x)=0\pmod {x^n}\)
\(F_*^{-2}(x)F(x)+F^{-1}(x)-2F_*^{-1}(x)=0\pmod {x^n}\)
\(F^{-1}(x)=(2-F_*^{-1}(x)\times F(x))F_*^{-1}(x)\)

递归 +NTT 即可。
边界: \(n=1\) 时,为 \(F(0)\) 的逆元。

3.多项式开根

\(G^2(x)-F(x)=0\pmod {x^n}\)

\(G_*^2(x)-F(x)=0 \pmod {x^{n/2}}\)
\(G(x)-G_*(x)=0\pmod {x^{n/2}}\).
\(G^2(x)+G^2_*(x)-2G(x)G_*(x)=0\pmod {x^n}\)
\(F(x)+G_*^2(x)-2G(x)G_*(x)\pmod {x^n}\)
\(G(x)=\dfrac{F(x)+G_*^2(x)}{2G_*(x)}\pmod {x^n}\).

同样地,考虑倍增求解即可。

4.多项式求 ln

\(G(x)=\ln F(x) \pmod {x^n}\)

\(G'(x)=\ln' (F(x))\times F'(x)\).
因为 \(\ln'x =\frac{1}{x}\),有 \(G'(x)=\dfrac{F'(x)}{F(x)}\pmod {x^n}\).
在把 \(G\) 积分回去即可。

5.多项式求 exp

\(G(x)=e^{F(x)} \pmod {x^n}\)

证明超出笔者能力。倍增:
\(G_*(x)=e^{F(x)}\pmod {x^{n/2}}\).
那么 \(G(x)=G_*(x)(1-\ln G_*(x)+F(x))\pmod {x^n}\).

6.多项式快速幂

考虑先 \(\ln\),翻 \(k\) 倍后 \(\exp\) 回去。

*7.分治 NTT

半在线卷积,求 \(f_i=\sum_{j=1}^nf_{i-j}g_j\).

考虑分治,对于当前分治到求 \(f_l\sim f_r\)
我们先求左边的 \(f_l\sim f_{mid}\),然后对 \(g_0\sim g_{r-l+1}\) 做个卷积,
把贡献加到 \(f_{mid+1}\sim f_r\) 即可。

事实上有求逆的解法,我们发现 \(F=1+F\times G\).
所以 \((1-G)\times F=1\),那么 \(F=(1-G)^{-1}\).

code
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=8e5+10;
const int p=998244353,g=3,gi=332748118;
const int inv2=499122177;
int tr[N],a[N],b[N],c[N],d[N];
int fpow(int x,int k) {
	int res=1;
	for(; k; k>>=1,x=1ll*x*x%p)
		if(k&1) res=1ll*res*x%p;
	return res;
}
void ntt(int *F,int n,int op) {
	for(int i=1; i<n; i++)
		tr[i]=(tr[i>>1]>>1)|((i&1)?n>>1:0);
	for(int i=1; i<n; i++) if(i<tr[i]) swap(F[i],F[tr[i]]);
	for(int len=2; len<=n; len<<=1)
		for(int i=0; i<n; i+=len) {
			int w=fpow(op==1?g:gi,(p-1)/len),buf=1;
			for(int j=i; j<i+len/2; j++) {
				int tmp=1ll*F[j+len/2]*buf%p;
				F[j+len/2]=(F[j]-tmp+p)%p;
				F[j]=(F[j]+tmp)%p;
				buf=1ll*buf*w%p;
			}
		}
	if(op!=1) {
		int tmp=fpow(n,p-2);
		for(int i=0; i<n; i++) F[i]=1ll*F[i]*tmp%p;
	}
}
void mul(int *F,int *G,int n,int *res) {
	ntt(F,n,1); ntt(G,n,1);
	for(int i=0; i<n; i++) res[i]=1ll*F[i]*G[i]%p;
	ntt(res,n,-1);
}
void getinv(int *F,int *res,int n) {
	if(n==1) return res[0]=fpow(F[0],p-2),void();
	getinv(F,res,(n+1)>>1);
	int lim=1;
	while(lim<(n<<1)) lim<<=1;
	for(int i=0; i<n; i++) c[i]=F[i];
	for(int i=n; i<lim; i++) c[i]=0;
	ntt(c,lim,1); ntt(res,lim,1);
	for(int i=0; i<lim; i++) res[i]=1ll*(2-1ll*c[i]*res[i]%p+p)*res[i]%p;
	ntt(res,lim,-1);
	for(int i=n; i<lim; i++) res[i]=0;
	for(int i=0; i<lim; i++) c[i]=0;
}
void getsqrt(int *F,int *res,int n) {
	if(n==1) return res[0]=1,void();
	getsqrt(F,res,(n+1)>>1);
	int lim=1;
	while(lim<(n<<1)) lim<<=1;
	for(int i=0; i<lim; i++) d[i]=0;
	getinv(res,d,n);
	for(int i=0; i<n; i++) c[i]=F[i];
	for(int i=n; i<lim; i++) c[i]=0;
	ntt(c,lim,1); ntt(d,lim,1); ntt(res,lim,1);
	for(int i=0; i<lim; i++) res[i]=1ll*(res[i]+1ll*c[i]*d[i]%p)%p*inv2%p;
	ntt(res,lim,-1);
	for(int i=n; i<lim; i++) res[i]=0;
}
void getDao(int *F,int *res,int n) {
	for(int i=1; i<n; i++) res[i-1]=1ll*F[i]*i%p;
	res[n-1]=0;
}
void getjf(int *F,int *res,int n) {
	for(int i=1; i<n; i++) res[i]=1ll*F[i-1]*fpow(i,p-2)%p;
	res[0]=0;
}
void getln(int *F,int *res,int n) {
	int lim=1;
	while(lim<(n<<1)) lim<<=1;
	for(int i=0; i<lim; i++) res[i]=0;
	getinv(F,res,n); getDao(F,c,n);
	ntt(res,lim,1); ntt(c,lim,1);
	for(int i=0; i<lim; i++) c[i]=1ll*res[i]*c[i]%p;
	ntt(c,lim,-1);
	getjf(c,res,n);
	for(int i=0; i<lim; i++) c[i]=0;
}
void getexp(int *F,int *res,int n) {
	if(n==1) return res[0]=1,void();
	getexp(F,res,(n+1)>>1);
	getln(res,b,n);
	int lim=1;
	while(lim<(n<<1)) lim<<=1;
	b[0]=(F[0]-b[0]+p+1)%p;
	for(int i=1; i<n; i++) b[i]=(F[i]-b[i]+p)%p;
	for(int i=n; i<lim; i++) b[i]=0;
	ntt(b,lim,1); ntt(res,lim,1);
	for(int i=0; i<lim; i++) res[i]=1ll*res[i]*b[i]%p;
	ntt(res,lim,-1);
	for(int i=n; i<lim; i++) res[i]=0;
}
void getpow(int *F,int *res,int n,int k) {
	getln(F,a,n);
	for(int i=0; i<n; i++) a[i]=1ll*a[i]*k%p;
	getexp(a,res,n);
}
posted @ 2024-04-05 21:02  GloriousCc  阅读(1)  评论(0编辑  收藏  举报