首先,多项式有两种表示方式,系数表示和点值表示

对于两个多项式相乘而言,用系数表示进行计算是O(n^2)的

而用点值表示进行计算是O(n)的

那么我们自然就会去想如果把系数表示的多项式转化为点值表示的多项式进行计算,不就可以减少时间复杂度了么

然而,一般情况下系数表示的多项式想要转化成点值表示的多项式,或是点值表示的多项式想要转化成系数表示的多项式,复杂度都是O(n^2)的

但这只是一般情况

我们可以通过取特殊值把系数表示转化成点值表示,这样的话能把复杂度降到O(nlogn),这就是DFT了

同样通过求逆之类的操作可以把点值表示转换为系数表示,同样复杂度为O(nlogn),这就是IDFT了

嘛。。。

简单来说就是这样的吧

代码

//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define mpr make_pair
#define maxn 200005
#define inf (1<<30)
#define eps 1e-8
#define pi 3.1415926535897932384626
using namespace std; inline int read()
{
int ret=;bool fla=;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-'){fla=;ch=getchar();}
while(ch>=''&&ch<=''){ret=ret*+ch-'';ch=getchar();}
return fla?-ret:ret;
} struct cp{
db x,y;
}A[maxn],B[maxn],C[maxn],D[maxn]; int n,m,mx,len,rev[maxn],a[maxn],cnt[maxn]; cp operator + (const cp &x,const cp &y){return (cp){x.x+y.x,x.y+y.y};}
cp operator - (const cp &x,const cp &y){return (cp){x.x-y.x,x.y-y.y};}
cp operator * (const cp &x,const cp &y){return (cp){x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x};} void FFT(cp *a,int op)
{
for(int i=;i<n;++i) if(rev[i]>i) swap(a[i],a[rev[i]]);
for(int k=;k<n;k<<=)
{
cp omi=(cp){cos(pi/k),sin(pi/k)*op};
for(int i=;i<n;i+=(k<<))
{
cp w=(cp){1.0,0.0};
for(int j=;j<k;++j,w=w*omi)
{
cp x=a[i+j],y=a[i+j+k]*w;
a[i+j]=x+y,a[i+j+k]=x-y;
}
}
}
if(op==-) for(int i=;i<n;++i) a[i].x/=n;
} int main()
{
n=read();
for(int i=,x;i<=n;++i) x=read(),mx=max(mx,*x),A[x].x=,B[x*].x=,C[x*].x=;
m=mx;
for(n=;n<=m;n<<=) len++;
for(int i=;i<n;++i) rev[i]=(rev[i>>]>>)|((i&)<<(len-));
FFT(A,);FFT(B,),FFT(C,);
for(int i=;i<n;++i)
{
cp tmp1=(cp){1.0/6.0,};
cp tmp2=(cp){3.0,};
cp tmp3=(cp){2.0,};
cp tmp4=(cp){1.0/2.0,};
D[i]=(A[i]*A[i]*A[i]-tmp2*B[i]*A[i]+tmp3*C[i])*tmp1;
D[i]=D[i]+(A[i]*A[i]-B[i])*tmp4;
D[i]=D[i]+A[i];
}
FFT(D,-);
for(int i=;i<n;++i)
{
int pri=(int)(D[i].x+0.5);
if(pri>) printf("%d %d\n",i,pri);
}
return ;
}

最新文章

  1. Microsoft Visual Studio 2008 未能正确加载包“Visual Web Developer HTML Source Editor Package” | “Visual Studio HTM Editor Package”
  2. k近邻
  3. Tomcat+Nginx+Lvs部署方案与性能调优
  4. PHP5.3中关于VC9和VC6以及Thread Safe和Non Thread Safe版本选择的问题
  5. perl中的grep函数介绍
  6. http://blogs.msdn.com/b/pranavwagh/archive/2007/03/03/word-2007-file-seems-to-be-deleted-when-you-open-and-save-it-using-dsoframer.aspx
  7. sql常识-Alias
  8. Python基础-简单输出
  9. 强大的数据恢复软件--EasyRecovery专业版
  10. 杭电oj1326 Box of Bricks
  11. HDU ACM 1065 I Think I Need a Houseboat
  12. c#面向对象-类(类及其构成)
  13. Linux入门之常用命令(12)用户管理
  14. poj3070矩阵快速幂
  15. java接口与抽象类
  16. python字典结构化数据
  17. linux安装jdk1.8.0_91
  18. docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面
  19. Java中的引用传递和值传递
  20. 奇怪吸引子---NoseHoover

热门文章

  1. APT和它的超级牛力
  2. 什么样子的WordPress网站更受搜索引擎欢迎
  3. npm WARN saveError ENOENT: no such file or directory, open &#39;C:\Users\James\package.json&#39;
  4. Tomcat:使用startup.bat启动tomcat遇到报错
  5. 14Shell脚本—判断语句
  6. linux关于任务计划
  7. python 程序小测试
  8. Applied Nonparametric Statistics-lec9
  9. JAVA基础篇—String和StringBuffer
  10. PAT Basic 1075