此后如竟没有炬火 我便是唯一的光|

Day_Dreamer_D

园龄:3年6个月粉丝:3关注:16

2022-10-26 19:29阅读: 18评论: 0推荐: 0

BZOJ 2194 快速傅里叶之二 题解

题目描述

求:ck=(ai×bik)

推导

一般卷积是和一定,然而这个是差一定,于是我们考虑把 b 反过来(其实反 a 也可以)。

ck=i=kn1(ai×bn+ki)

dk=i=kn1(ai×bki)

ck=dn+k

dk 的推导很像卷积,考虑将其变换形式,即 dn+k=i=0n+k(ai×bn+ki)

至此,可以通过 FFT 来求解。

/*
* Title: #2194. 快速傅立叶之二
* Source: HydroOJ-BZOJ
* URL: https://hydro.ac/d/bzoj/p/2194
* Author: Steven_lzx
* Command: -std=c++23 -Wall -fno-ms-extensions
*/
#include <bits/stdc++.h>
using namespace std;
typedef complex<double> cd;
const int MAXN=1<<20;
const double PI=acos(-1),TAU=2*PI;
cd a[MAXN],b[MAXN];
void FFT(cd *a,int n,int dft)
{
cd w,wk,x,y;
for(int i=0,k=0;i<n;i++)
{
if(i>k)
swap(a[i],a[k]);
for(int j=n>>1;(k^=j)<j;j>>=1);
}
for(int k=2;k<=n;k<<=1)
{
w=cd(cos(TAU*dft/k),sin(TAU*dft/k));
for(int i=0;i<n;i+=k)
{
wk=cd(1,0);
for(int j=0;j<(k>>1);j++)
{
x=a[i+j];
y=wk*a[i+j+(k>>1)];
a[i+j]=x+y;
a[i+j+(k>>1)]=x-y;
wk*=w;
}
}
}
return;
}
int main()
{
int n,len;
double x,y;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&x,&y);
a[i]=cd(x,0);
b[n-i-1]=cd(y,0);
}
for(len=1;len<=(n<<1);len<<=1);
FFT(a,len,1);
FFT(b,len,1);
for(int i=0;i<len;i++)
{
a[i]*=b[i];
}
FFT(a,len,-1);
for(int i=n-1;i<(n<<1)-1;i++)
printf("%lld\n",(long long)(a[i].real()/len+0.1));
return 0;
}

本文作者:Day_Dreamer_D

本文链接:https://www.cnblogs.com/2020gyk080/p/16829752.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Day_Dreamer_D  阅读(18)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起