FFT

#include <bits/stdc++.h>
using namespace std;
#define N 301000
const double pi=acos(-1);
struct node{
    double x,y;
    node(){x=y=0;}
    node(double x,double y):x(x),y(y){}
}a[N],b[N];
node operator + (node x,node y) {return node(x.x+y.x,x.y+y.y);}
node operator - (node x,node y) {return node(x.x-y.x,x.y-y.y);}
node operator * (node x,node y) {return node(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
void fft(node *s,int n,int t){
//t就是标记它是不是逆的FFT,最后不是要从点值表达转回系数表达吗t=-1表示处理这个
//用ωn^(-1)替换ωn 并将计算结果的每个元素除以n。
    if (n==1) return;
    node a0[n>>1],a1[n>>1];
    for (int i=0;i<=n;i+=2)a0[i>>1]=s[i],a1[i>>1]=s[i+1];//根分成两半
    fft(a0,n>>1,t);fft(a1,n>>1,t);//分治
    node wn(cos(2*pi/n),t*sin(2*pi/n)),w(1,0);//就是ω开始每次转wn角度
    //如果要算ωn^(-1)的话 根据负数的指数形式的定义e^(iu)=cos(u)+isin(u)
    //ωn^(-1)=e^(-2πi/n) 设u=2πi/n e^(-2πi/n)=cos(-u)+isin(-u)=cos(u)-isin(u)
    //所以如果反过来的话 让sin乘个t=-1就好了
    for (int i=0;i<(n>>1);i++,w=w*wn)//对根归并
    s[i]=a0[i]+w*a1[i],s[i+(n>>1)]=a0[i]-w*a1[i];
    //w^2=(w+n/2)^2 均匀分布在圆上面
    //w[i^2,n]=w[i/2,n/2] 折半引理
    //s[i]=a0’(i^2)+i*a1’(i^2)=a0(i)+i*a1(i)
    //s[i+n/2]=a0’((i+n/2)^2)+i*a1’((i+n/2)^2)=a0’(i^2)-i*a1’(i^2)
    //因为i=-(i+n/2) 折半引理
}
int main(){
    int n,m,fn,i;
    scanf("%d%d",&n,&m);
    for (i=0;i<=n;i++) scanf("%lf",&a[i].x);
    for (i=0;i<=m;i++) scanf("%lf",&b[i].x);
    fn=1;while (fn<=n+m) fn<<=1;
    fft(a,fn,1);fft(b,fn,1);
    for (i=0;i<=fn;i++) a[i]=a[i]*b[i];
    fft(a,fn,-1);
for (i=0;i<=n+m;i++)
printf("%d ",(int)(a[i].x/fn+0.5));//强转int会自动向下取整所以要加0.5让它四舍五入
    printf("\n");
    return 0;
}
FFT快速傅里叶变换-递归版
uoj#34多项式乘法题意:给两多项式,输出乘起来后的多项式
In			out
1			1 4 5 2
2
1 2
1 2 1

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值