FFT什么的
来源:互联网 发布:weka 聚类算法 编辑:程序博客网 时间:2024/04/25 02:35
这里只有公式&做法,没有复杂的证明(其实是因为弱鸡yww不会)
参考自国家集训队论文&各个博客
多项式
一个以
我们称
如果一个多项式的最高次的非零系数是
我们在多项式上可以定义很多不同的运算。
多项式加法
如果
则
其中
例如,如果
则
多项式乘法
如果
例如,如果
则
多项式的表示
系数表达
对一个次数界为
我们可以用秦久韶算法在
类似的,对于两个分别用系数向量
现在来考虑两个用系数形式表达的次数界为
点值表达
一个次数界为
使得对
一个多项式可以有很多不同的点值表达,因为可以采用
朴素的求值是
求值的逆称为插值。当插值多项式的次数界等于已知的点值对的数目时,插值才是明确的。
我们可以在用高斯消元在
以上求值和插值可以将多项式的系数表达和点值表达进行相互转化,上面给出的算法的时间复杂度是
对于许多多项式相关的操作,点值表达式很便利的。
对于加法,如果
和
(注意,
因此,对两个点值形式表示的次数界为
类似的,如果
和
(注意,
因此,对两个点值形式表示的次数界为
最后,我们考虑一个采用点值表达的多项式,如何求其在某个新点上的值。最简单的方法是把该多项式转成系数形式表达,然后在新点处求值。
系数形式表示的多项式的快速乘法
如果我们选
DFT&FFT&IDFT
单位复数根
消去引理:对任何整数
DFT
回顾一下,我们希望计算次数界为
向量
FFT
利用单位复数根的特殊性质,我们可以在
FFT利用了分治策略。
我们令
对于
对于
这样我们把
IDFT
通过推导公式,我们得到:
所以我们可以用类似FFT的方法在
多项式乘法
我们可以在
蝶形运算
我们把由
我们发现,递归时
总的蝶形运算是长这样的:
可以发现,最后
NTT
在某些时候,我们需要求模
先求出
时间上的优化
令
这样我们就可以求出
这个方法可以把
多项式求导
给定
多项式积分
给定
多项式求逆
多项式
下面介绍一个
首先求出
假设已求出满足
的
我们可以用
多项式开根
已知
可能可以用ln&exp来算。
先求出
假设已求出满足
的
我们可以在
时间复杂度:
多项式ln
给定形式幂级数
给定多项式
则
只需要求出
多项式exp
给定形式幂级数
令
考虑用牛顿迭代解这一方程。首先
设以求得
作泰勒展开得
即
把上面那个式子带入得
时间复杂度:
多项式除法
给你
若
举个例子:比如说
相当于把
我们设
然后我们把这个式子放在模
因为
然后把
时间复杂度:
多点求值
给你一个多项式
考虑一个简单的做法:构造
设当前求值的点为
构造多项式
那么当
每一层计算
总的时间复杂度就是
快速插值
模板
#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<ctime>#include<utility>#include<cmath>#include<functional>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> pii;typedef pair<ll,ll> pll;void sort(int &a,int &b){ if(a>b) swap(a,b);}void open(const char *s){#ifndef ONLINE_JUDGE char str[100]; sprintf(str,"%s.in",s); freopen(str,"r",stdin); sprintf(str,"%s.out",s); freopen(str,"w",stdout);#endif}int rd(){ int s=0,c; while((c=getchar())<'0'||c>'9'); do { s=s*10+c-'0'; } while((c=getchar())>='0'&&c<='9'); return s;}int upmin(int &a,int b){ if(b<a) { a=b; return 1; } return 0;}int upmax(int &a,int b){ if(b>a) { a=b; return 1; } return 0;}const ll p=998244353;const ll g=3;ll fp(ll a,ll b){ ll s=1; while(b) { if(b&1) s=s*a%p; a=a*a%p; b>>=1; } return s;}const int maxn=600000;ll inv[maxn];namespace ntt{ ll w1[maxn]; ll w2[maxn]; int rev[maxn]; int n; void init(int m) { n=1; while(n<m) n<<=1; int i; for(i=2;i<=n;i<<=1) { w1[i]=fp(g,(p-1)/i); w2[i]=fp(w1[i],p-2); } rev[0]=0; for(i=1;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)*(n>>1)); } void ntt(ll *a,int t) { int i,j,k; ll u,v,w,wn; for(i=0;i<n;i++) if(rev[i]<i) swap(a[i],a[rev[i]]); for(i=2;i<=n;i<<=1) { wn=(t==1?w1[i]:w2[i]); for(j=0;j<n;j+=i) { w=1; for(k=j;k<j+i/2;k++) { u=a[k]; v=a[k+i/2]*w%p; a[k]=(u+v)%p; a[k+i/2]=(u-v)%p; w=w*wn%p; } } } if(t==-1) { u=fp(n,p-2); for(i=0;i<n;i++) a[i]=a[i]*u%p; } } ll x[maxn]; ll y[maxn]; ll z[maxn]; void copy_clear(ll *a,ll *b,int m) { int i; for(i=0;i<m;i++) a[i]=b[i]; for(i=m;i<n;i++) a[i]=0; } void copy(ll *a,ll *b,int m) { int i; for(i=0;i<m;i++) a[i]=b[i]; } void mul(ll *a,ll *b,ll *c,int m) { init(m<<1); copy_clear(x,a,m); copy_clear(y,b,m); ntt(x,1); ntt(y,1); int i; for(i=0;i<n;i++) x[i]=x[i]*y[i]%p; ntt(x,-1); copy(c,x,m); } void inverse(ll *a,ll *b,int m) { if(m==1) { b[0]=fp(a[0],p-2); return; } inverse(a,b,m>>1); init(m<<1); copy_clear(x,a,m); copy_clear(y,b,m>>1); ntt(x,1); ntt(y,1); int i; for(i=0;i<n;i++) x[i]=y[i]*(2-x[i]*y[i]%p)%p; ntt(x,-1); copy(b,x,m); } ll c[maxn],d[maxn],e[maxn],f[maxn]; void sqrt(ll *a,ll *b,int m) { if(m==1) { if(a[0]==1) b[0]=1; else if(a[0]==0) b[0]=0; else //我也不会 ; return; } sqrt(a,b,m>>1);// copy_clear(c,b,m>>1); int i; for(i=m;i<m<<1;i++) b[i]=0; inverse(b,d,m); init(m<<1); for(i=m;i<m<<1;i++) b[i]=d[i]=0; ll inv2=fp(2,p-2); copy_clear(x,a,m); ntt(x,1); ntt(d,1); for(i=0;i<n;i++) x[i]=x[i]*d[i]%p; ntt(x,-1); for(i=0;i<m;i++) b[i]=((b[i]+x[i])%p*inv2)%p; } void derivative(ll *a,ll *b,int m) { int i; for(i=0;i<m-1;i++) b[i]=(i+1)*a[i+1]%p; b[m-1]=0; } void differential(ll *a,ll *b,int m) { int i; for(i=m-1;i>=1;i--) b[i]=a[i-1]*inv[i]%p; b[0]=0; } void ln(ll *a,ll *b,int m) { static ll c[maxn],d[maxn]; derivative(a,c,m); inverse(a,d,m); init(m<<1); int i; for(i=m;i<n;i++) c[i]=d[i]=0; ntt(c,1); ntt(d,1); for(i=0;i<n;i++) c[i]=c[i]*d[i]%p; ntt(c,-1); differential(c,b,m); } void exp(ll *a,ll *b,int m) { if(m==1) { b[0]=1; return; } exp(a,b,m>>1); int i; for(i=m>>1;i<m;i++) b[i]=0; ln(b,y,m); init(m<<1); copy_clear(x,a,m); x[0]++; for(i=0;i<m;i++) x[i]=(x[i]-y[i])%p; copy_clear(y,b,m); ntt(x,1); ntt(y,1); for(i=0;i<n;i++) x[i]=x[i]*y[i]%p; ntt(x,-1); copy(b,x,m); } void module(ll *a,ll *b,ll *c,int n1,int n2) { int k=1; while(k<=n1-n2+1) k<<=1; int i; for(i=0;i<=n1;i++) d[i]=a[i]; for(i=0;i<=n2;i++) e[i]=b[i]; reverse(d,d+n1+1); reverse(e,e+n2+1); for(i=n1-n2+1;i<k<<1;i++) d[i]=e[i]=0; inverse(e,f,k); for(i=n1-n2+1;i<k<<1;i++) f[i]=0; init(k<<1); ntt::ntt(d,1); ntt::ntt(f,1); for(i=0;i<n;i++) e[i]=d[i]*f[i]%p; ntt::ntt(e,-1); for(i=0;i<=n1-n2;i++) c[i]=e[i]; reverse(c,c+n1-n2+1); }};ll b[maxn];ll a[maxn];ll c[maxn];void get(ll *a,int n){ int i; for(i=0;i<n;i++) a[i]=rand();}int main(){// freopen("fft.txt","w",stdout);// srand(time(0));// int n=262144;// int bg,ed;// int i;// int times=100,j;// double s,s1;// inv[0]=inv[1]=1;// for(i=2;i<=n;i++)// inv[i]=-(p/i)*inv[p%i]%p;// s=0;// for(j=1;j<=times;j++)// {// get(a,n);// bg=clock();// ntt::init(n);// ntt::ntt(a,1);// ed=clock();// s+=double(ed-bg)/CLOCKS_PER_SEC;// }// printf("ntt :%.10lf\n",s/times);// s1=s;// s=0;// for(j=1;j<=times;j++)// {// get(a,n);// get(b,n);// bg=clock();// ntt::mul(a,b,c,n);// ed=clock();// s+=double(ed-bg)/CLOCKS_PER_SEC;// }// printf("mul :%.10lf %.10lf\n",s/times,s/s1);// s=0;// for(j=1;j<=times;j++)// {// get(a,n);// bg=clock();// ntt::inverse(a,b,n);// ed=clock();// s+=double(ed-bg)/CLOCKS_PER_SEC;// }// printf("inv :%.10lf %.10lf\n",s/times,s/s1);// s=0;// for(j=1;j<=times;j++)// {// get(a,n);// a[0]=1;// bg=clock();// ntt::sqrt(a,b,n);// ed=clock();// s+=double(ed-bg)/CLOCKS_PER_SEC;// }// printf("sqrt:%.10lf %.10lf\n",s/times,s/s1);// s=0;// for(j=1;j<=times;j++)// {// get(a,n);// a[0]=1;// bg=clock();// ntt::ln(a,b,n);// ed=clock();// s+=double(ed-bg)/CLOCKS_PER_SEC;// }// printf("ln :%.10lf %.10lf\n",s/times,s/s1);// s=0;// for(j=1;j<=times;j++)// {// get(a,n);// bg=clock();// ntt::exp(a,b,n);// ed=clock();// s+=double(ed-bg)/CLOCKS_PER_SEC;// }// printf("exp :%.10lf %.10lf\n",s/times,s/s1);// return 0;}
- FFT什么的
- FFT
- "fft"
- FFT
- fft
- FFT
- fft
- FFT
- FFT
- FFT
- FFT
- fft
- FFT
- FFT
- fft
- FFT
- fft
- FFT
- 31、互斥锁与进程间通信
- Cookie总结
- C#枚举中的位运算权限分配
- MOOC清华《面向对象程序设计》第4章:函数模板实验
- c++结构体struct的一些例子
- FFT什么的
- CodeForces 674 D.Bearish Fanpages(set+multiset)
- hadoop配置文件加载顺序
- 游戏开发中的工具类之单例模式的复用
- 读论文《The perceptron: A probabilistic model for information storage and organization in the brain》
- 1.9volatile
- Milky(Way) 大佬
- R————KNN
- 连接数据库以及增删改查