忘光了,所以复习【POL】
防爬标记:作者 TOBapNw-cjn,网址 https://www.cnblogs.com/TOBapNwCJN/p/16530792.html。
更新于 2022/8/30 17:30
拉格朗日插值
给定
朴素拉格朗日插值
只求
作
所以,如果构造了
接下来构造:
所以:
这样就可以
带入即可。
坐标连续时的拉格朗日插值
代入得
仔细观察一下,可以发现,我们只要预处理前后缀
所以:
就可以
设答案为一个
次多项式 。 直接带入前
个点,然后用坐标连续时的拉格朗日插值即可。
重心拉格朗日插值
支持动态加点。
考虑:
然后维护
可以做到
求出多项式每一项的系数
提出系数,那么
所以预处理时先暴力卷出
复杂度
然后我就写了一个程序得出了以下著名函数:
多项式乘法
快速傅里叶变换(FFT)
快速卷积。
离散傅里叶变换(DFT)
DFT,把一个多项式从系数表示法转化为点值表示法。
为什么要转成点值表示法呢?
考虑两个多项式乘起来,只要装换成点值,然后把点值相乘即可。
单位根
设两个多项式次数分别为
大多数想法是取任意
所以考虑一些特殊点。
这时候就要取到单位根了。
一共有
在复数域中只有以
性质
对于上标
-
定有一个根
。 -
考虑乘上一个
表示把当前向量转一个 的圆周。 -
由上一条简单得出。
-
考虑
。 -
仔细想一想就知道是对的,并且
。 -
对于一个偶数
,有把
看做旋转 圈即可。
求单位根
首先
考虑
快速傅里叶变换(FFT)
考虑一个多项式
此部分设
即:
这里需要保证
然后设:
则:
代入单位根:
-
代入
: -
代入
:
我们把二者对比一下:之差了一个符号!这时候就开始体会到单位根的牛了。
在这个时候,如果我们知道了
那么我们就可以递归求出所有点值,不难发现递归共
所以复杂度为
快速傅里叶逆变换(IFFT)
首先有一个结论:
证明:
首先有:
讨论:
-
,所以 一共有 次被计算到,答案为 。 -
设
,所以贡献为可以发现后面有个等比数列求和:
所以就证完了。
可以发现根据这个式子,我们只要改变一下单位根的旋转方向(把旋转一个单元变为
具体的,只要改变单位根里的一个符号即可。
代码
代码(处理单位根):
inline void init(Ci N,const bool op){
o.resize(max(N,2));
o[0]={1,0};o[1]={cos(PI/N),(op?1:-1)*sin(PI/N)};
for(int i=2;i<N;i++)o[i]=o[i-1]*o[1];
}
代码(FFT):
void fft(vector<Cp>&f,Ci n,const bool op){
if(n==1)return;
vector<Cp>f0,f1;int m=n>>1;
f0.resize(m);f1.resize(m);
for(int i=0;i<m;i++)f0[i]=f[i<<1],f1[i]=f[i<<1|1];
fft(f0,m,op);fft(f1,m,op);
init(m,op);
for(int i=0;i<m;i++){
f[i]=f0[i]+o[t][i]*f1[i];
f[i+m]=f0[i]-o[t][i]*f1[i];
}
}
代码(多项式乘法):
inline void fft(){fft(x,x.size(),1);}
inline void Ifft(){fft(x,x.size(),0);}
inline friend Poly operator*(Poly U,Poly V){
int S=U.size()+V.size()-1;
int u=1;while(u<S)u<<=1;
U.resize(u);V.resize(u);
U.fft();V.fft();
for(int i=0;i<u;i++)U[i]*=V[i];
U.Ifft();
for(int i=0;i<u;i++)U[i].x/=u;
return U;
}
蝴蝶变换
我们的递归版是递归到最下面然后合并上来。
我们直接到最下面然后直接合并。
考虑按奇偶性分组的本质是按当前二进制位向左或向右,正好与原标号二进制相反,所以最后一层的标号即为位置序号的翻转。
感觉不太说的清楚,看图:
比如上图中第
接下来,如何快速翻转二进制呢?
设翻转后的数组为
把二进制串
可以发现只要删去最后一位,再加个最高位就行了。
代码(迭代 FFT):
for(int l=2,t=1;l<=n;l<<=1,t++)
for(vector<Cp>::iterator i=f.begin();i!=f.end();i+=l){
int m=l>>1;
for(int j=0;j<m;j++){
Cp tmp=o[(n>>t)*j]*i[j+m];
i[j+m]=i[j]-tmp;i[j]+=tmp;
}
}
给出
个数 ,定义 对
,求 的值。 , 。 这个东西其实是一个普通卷积和一个减法卷积,分别算即可。
快速数论变换(NTT)
NTT
由于 FFT 需要用到单位根,不可避免的就会有精度误差,而且也有较大的常数,数学家们已经证明,在复数域中,单位根是唯一一类满足要求的数。
不过 OI 中不少题在模意义下,所以我们考虑同余系中的原根。
对于模数
可以构造在模意义下满足单位根性质的
不难发现需要满足
这在
任意模数NTT
用 3 个 NTT 模数,最后 CRT 合并即可。
分治 FFT/NTT
考虑
关于递推的分治方法就是每次算左半边对右半边的贡献。
多项式求逆
由于
设
设
首先有:
所以就可以递推了。
复杂度
多项式带余除法
求
满足
设
把
设
可以发现用一下求逆即可。
多项式对数函数(ln)
求
满足
导数和积分都可以直接来。
多项式指数函数(exp)
求
满足
牛顿迭代
不难发现上面的方法做不了。
引入牛顿迭代的问题:
求
满足
考虑求逆的递推思路,设
假设当前求出了
将
可以发现,
所以
复杂度同求逆:
exp
设
然后就可以递推了。
多项式快速幂
求
满足 。
然后就是 exp。
多项式开根
求
满足 。
设
多项式快速幂。
多项式多点求值
给定
,长度为 的多项式 以及数组 ,求所有 。
分治。
设
可以发现,对于
然后发现我们可以分治 NTT 预处理
多项式快速插值
拉插的式子:
发现后面
可以洛必达
所以分治 NTT 后多点求值。
设
GL&HF
目前就这些,有问题请指出,之后可能会再施工。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】