丑陋敬请谅解:

求两列数的卷积:

递归版:

#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. 微信小程序测试request请求webapi

    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...

  2. 神奇的navigationBar.translucent

    初步实践所得: 当translucent属性为YES的时候,vc的view的坐标从导航栏的左上角开始: 当translucent属性为NO的时候,vc的view的坐标从导航栏的左下角开始:   深入探 ...

  3. python导入第三方库

    2.Python的库一般包含两个方面:第三方库和标准库 3.Python的time标准库主要包含三个方面的内容:(1)时间处理函数(2)时间格式化(3)程序计时 4.turtle画笔运动函数的功能是进 ...

  4. vue v-model 数据双向绑定(笔记)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. java猜拳

    import java.util.Scanner; public class startGuess { Person jia; Computer yi; int count; public void ...

  6. linux动态库(.so)和静态库(.a)的区别

    静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.编译之后程序文件大,但加载快,隔离性也好. 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时 ...

  7. Linux centos7 sed工具介绍

    一.sed上 grep工具功能只能实现查找,不能把查找的内容替换. sed本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行查找.删除.替换字符或字符串.调换字符串位置.直接修改文件内容等 ...

  8. 回文数索引(string类erase解题)

    题目描述 给定一个仅由小写字母组成的字符串.现在请找出一个位置,删掉那个字母之后,字符串变成回文.请放心总会有一个合法的解.如果给定的字符串已经是一个回文串,那么输出-1. 输入描述: 第一行包含T, ...

  9. 【Go语言系列】2.2、Go语言基本程序结构:关键字与标识符

    什么是标识符 标识符用来命名变量.类型等程序实体.标识符是指Go语言对各种变量.方法.函数等命名时使用的字符序列,标识符由若干个字母.下划线_.和数字组成,且第一个字符必须是字母.通俗的讲就是凡可以自 ...

  10. WPBakery Page Builder页面生成器6.0 汉化版

    WPBakery Page Builder 是一个可视化编辑器插件 ,相较于WP自带的编辑器使用起来更加方便,同时功能更 加强大,完全的可视化操作,使用比较简单,国外有多款主题需要使用插件. WPBa ...