丑陋敬请谅解:

求两列数的卷积:

递归版:

#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
const double pi=acos(-);
int p[],q[];
struct complex
{
double x,y;
complex(double xx=,double yy=)
{
x=xx;
y=yy;
}
}a[],b[];
complex operator +(complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
complex operator -(complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
complex operator *(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
void DFT(int limit,complex *a)
{
if(limit==)
return;
int mid=limit>>;
complex a1[mid],a2[mid];
for(int i=;i<=limit;i+=)
{
a1[i>>]=a[i];
a2[i>>]=a[i+];
}
DFT(mid,a1);
DFT(mid,a2);
complex wn=complex(cos(2.0*pi/limit),sin(2.0*pi/limit));
complex w=complex(,);
for(int i=;i<mid;i++,w=w*wn)
{
a[i]=a1[i]+w*a2[i];
a[i+mid]=a1[i]-w*a2[i];
}
}
int pow(int x,int y)
{
if(y==)
return ;
int t=pow(x,y/);
if(y%==)
return t*t;
return t*t*x;
}
void IDFT(int limit,complex *a)
{
if(limit==)
return;
int mid=limit>>;
complex a1[mid],a2[mid];
for(int i=;i<=limit;i+=)
{
a1[i>>]=a[i];
a2[i>>]=a[i+];
}
IDFT(mid,a1);
IDFT(mid,a2);
complex wn=complex(cos(2.0*pi/limit),-sin(2.0*pi/limit));
complex w=complex(,);
for(int i=;i<mid;i++,w=w*wn)
{
a[i]=a1[i]+w*a2[i];
a[i+mid]=a1[i]-w*a2[i];
}
}
int main()
{
int k;
scanf("%d",&k);
int n=pow(,k);
for(int i=;i<=n-;i++)
scanf("%d",&p[i]);
for(int i=;i<=n-;i++)
scanf("%d",&q[i]);
for(int i=;i<=n-;i++)
a[i]=p[i];
for(int i=;i<=n-;i++)
b[i]=q[i];
int limit=*n;
DFT(limit,a);
DFT(limit,b);
for(int i=;i<=limit;i++)
a[i]=a[i]*b[i];
IDFT(limit,a);
for(int i=;i<=n-;i++)
printf("%d\n",(int)(a[i].x/limit+0.5));
printf("%d",(int)(a[n-].x/limit+0.5));
}

非递归版+蝶形算法优化:

#include<stdio.h>
#include <algorithm>
#include<math.h>
using namespace std;
const int MAXN=1e7+;
const double Pi=acos(-1.0);
int p[MAXN],q[MAXN];
struct complex
{
double x,y;
complex (double xx=,double yy=){x=xx,y=yy;}
}a[MAXN],b[MAXN];
complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);}
complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);}
complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);}
int N,M;
int l,r[MAXN];
int limit=;
void DFT(complex *A)
{
for(int i=;i<limit;i++)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=)
{
complex Wn( cos(Pi/mid) , sin(Pi/mid) );
for(int R=mid<<,j=;j<limit;j+=R)
{
complex w(,);
for(int k=;k<mid;k++,w=w*Wn)
{
complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y;
A[j+mid+k]=x-y;
}
}
}
}
void IDFT(complex *A)
{
for(int i=;i<limit;i++)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=)
{
complex Wn( cos(Pi/mid) , -1.0*sin(Pi/mid) );
for(int R=mid<<,j=;j<limit;j+=R)
{
complex w(,);
for(int k=;k<mid;k++,w=w*Wn)
{
complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y;
A[j+mid+k]=x-y;
}
}
}
}
int main()
{
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++) scanf("%d",&p[i]);
for(int i=;i<=M;i++) scanf("%d",&q[i]);
for(int i=;i<=N;i++) a[i]=p[i];
for(int i=;i<=M;i++) b[i]=q[i];
while(limit<=N+M) limit<<=,l++;
for(int i=;i<limit;i++)
r[i]= ( r[i>>]>> )| ( (i&)<<(l-) ) ;
DFT(a);
DFT(b);
for(int i=;i<=limit;i++) a[i]=a[i]*b[i];
IDFT(a);
for(int i=;i<=N+M;i++)
printf("%d ",(int)(a[i].x/limit+0.5));
return ;
}

FFT版高精度乘法:

#include<stdio.h>
#include <algorithm>
#include<math.h>
#include <string.h>
using namespace std;
const double Pi=acos(-1.0);
char s1[],s2[];
int sum[];
struct complex
{
double x,y;
complex (double xx=,double yy=){x=xx,y=yy;}
}a[],b[];
complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);}
complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);}
complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);}
int N,M,L;
int len=;
int l,r[];
int limit=;
void fft(complex *A,int limit,int type)
{
for(int i=;i<limit;i++)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=)
{
complex Wn( cos(Pi/mid) , type*sin(Pi/mid) );
for(int R=mid<<,j=;j<limit;j+=R)
{
complex w(,);
for(int k=;k<mid;k++,w=w*Wn)
{
complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y;
A[j+mid+k]=x-y;
}
}
}
if(type==-)for(int i=;i<limit;i++)A[i].x/=limit;
}
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s1);
scanf("%s",s2);
int len1=strlen(s1);
int len2=strlen(s2);
int lenx=len1+len2;
for(len=;len<lenx;len<<=)
L++;
for(int i=;i<len;i++)
r[i]=((r[i>>])>>)|((i&)<<(L-));
for(int i=;i<len1;i++)
a[i]=complex(s1[len1-i-]-'',);
for(int i=len1;i<len;i++)
a[i]=complex(,);
for(int i=;i<len2;i++)
b[i]=complex(s2[len2-i-]-'',);
for(int i=len2;i<len;i++)
b[i]=complex(,);
fft(a,len,);fft(b,len,);
for(int i=;i<len;i++)
a[i]=a[i]*b[i];
fft(a,len,-);
for(int i=;i<len;i++)
sum[i]=int(a[i].x+0.5);
for(int i=;i<len;i++)
{
sum[i+]+=sum[i]/;
sum[i]%=;
}
len=len1+len2-;
while(sum[len]<= && len>)
len--;
for(int i=len;i>=;i--)
printf("%c",sum[i]+'');
return ;
}

FFT各种模板的更多相关文章

  1. FFT快速傅里叶模板

    FFT快速傅里叶模板…… /* use way: assign : h(x) = f(x) * g(x) f(x):len1 g(x):len2 1. len = 1; while(len < ...

  2. 多项式FFT相关模板

    自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h& ...

  3. 多项式FFT/NTT模板(含乘法/逆元/log/exp/求导/积分/快速幂)

    自己整理出来的模板 存在的问题: 1.多项式求逆常数过大(尤其是浮点数FFT) 2.log只支持f[0]=1的情况,exp只支持f[0]=0的情况 有待进一步修改和完善 FFT: #include&l ...

  4. hdu 1402 FFT(模板)

    A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  5. FFT/NTT模板 既 HDU1402 A * B Problem Plus

    @(学习笔记)[FFT, NTT] Problem Description Calculate A * B. Input Each line will contain two integers A a ...

  6. FFT NTT 模板

    NTT: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; # ...

  7. 多项式乘法(FFT)模板 && 快速数论变换(NTT)

    具体步骤: 1.补0:在两个多项式最前面补0,得到两个 $2n$ 次多项式,设系数向量分别为 $v_1$ 和 $v_2$. 2.求值:用FFT计算 $f_1 = DFT(v_1)$ 和 $f_2=DF ...

  8. 分治FFT/NTT 模板

    题目要我们求$f[i]=\sum\limits_{j=1}^{i}f[i-j]g[j]\;mod\;998244353$ 直接上$NTT$肯定是不行的,我们不能利用尚未求得的项卷积 所以要用$CDQ$ ...

  9. UOJ#34 FFT模板题

    写完上一道题才意识到自己没有在博客里丢过FFT的模板-- 这道题就是裸的多项式乘法,可以FFT,可以NTT,也可以用Karasuba(好像有人这么写没有T),也可以各种其他分治乘法乱搞-- 所以我就直 ...

随机推荐

  1. redis之string数据类型常用方法总结

    目录 redis 字符串(string)[需要掌握] 特点 语法 redis 字符串(string)[需要掌握] 特点 一个键能存储512MB数据 string类型是二进制安全的,可以存储任何数据,比 ...

  2. C语言入门书籍知识点记录

    1. 数据在内存中的存储(二进制存储) 内存条:电路的电压有两种状态:0V或者5V,对应的一个元器件有2种状态:0 或者1. 一般情况下我们不一个一个的使用元器件,而是将8个元器件看做一个单位. 一个 ...

  3. Day2-F-A Knight's Journey POJ-2488

    Background The knight is getting bored of seeing the same black and white squares again and again an ...

  4. leetcode142 Linked List Cycle II

    """ Given a linked list, return the node where the cycle begins. If there is no cycle ...

  5. 十五 JSP开发模式&MVC设计模式

    JSP开发模式: JavaBean + JSP  : 缺点:页面代码过多,不利于维护,JSP页面代码变得臃肿 Servlet + JavaBean + JSP :MVC设计模式 M:model   模 ...

  6. 虚拟机安装安全狗apache服务的一些问题解决方式(11.5)

    首先本文鸣谢bonga的解答大部分问题=.= 由于本人比较懒所以还是喜欢问,不喜欢查啦 1.windows网站安全狗分为:IIS  和  APACHE  版本    我下载的是APACHE版本 (因为 ...

  7. iOS 十种线程锁

    锁 是什么意思? 我们在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引发数据错乱和数据安全等问题,这时候就需要我们保证每次只有一个线程访问这一块资源,锁 应运而生. 这里顺便提一下,上锁 ...

  8. Oracle删除重复数据并且只留其中一条数据

    数据库操作中,经常会因为导数据造成数据重复,需要进行数据清理,去掉冗余的数据,只保留正确的数据 一:重复数据根据单个字段进行判断 1.首先,查询表中多余的数据,由关键字段(name)来查询. sele ...

  9. CentOS下安装Orcale

    以前没有安装过,最近安装了.感觉在Liunx安装真的超麻烦.这是技术文档,分享给大家. LINUX安装oracle数据库步骤: 1.安装依赖包    yum -y install  gcc gcc-c ...

  10. GoJS组织结构图

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...