并不对劲的DFT
FFT是一个很多人选择背诵全文的算法。
#include<algorithm>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define cd complex<double>
#define maxn 1000110
#define maxm (maxn<<1)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
const double pi=acos(-1);
int n,m,r[maxm],len;
cd a[maxm],b[maxm];
void fft(cd * c,double f)
{
rep(i,0,n-1)if(i<r[i])swap(c[i],c[r[i]]);
for(int i=1;i<n;i<<=1)
{
cd wn(cos(pi/i),sin(f*pi/i)),x,y;
for(int j=0;j<n;j+=(i<<1))
{
cd w(1,0);
rep(k,0,i-1)
x=c[j+k],y=w*c[j+i+k],c[j+k]=x+y,c[j+i+k]=x-y,w*=wn;
}
}
}
int main()
{
n=read(),m=read();
rep(i,0,n)a[i]=read();
rep(i,0,m)b[i]=read();
m+=n;
for(n=1;n<=m;n<<=1)len++;
rep(i,0,n-1)r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
fft(a,1),fft(b,1);
rep(i,0,n-1)a[i]*=b[i];
fft(a,-1);
rep(i,0,m)printf("%d ",int(a[i].real()/n+0.5));
return 0;
}
并不对劲的大剑使认为有必要说明为什么IDFT最后要除以n。
假设原函数是\(F(x)=a_0x^0+a_1x^1+...+a_{n-1}x^{n-1}\)
那么对它进行DFT,将\(\omega_n^0,\omega_n^1,...,\omega_n^{n-1}\)依次代入,得到\(y_0,y_1,...,y_{n-1}\)
设\(G(x)=y_0x^0+y_1x^1+...+y_{n-1}x^{n-1}\)
IDFT就是已知G每一项的系数,求F每一项的系数
先对G进行DFT,将\(\omega_n^0,\omega_n^{-1},...,\omega_n^{-(n-1)}\)依次代入,得到\(z_0,z_1,...,z_{n-1}\)
那么就会有$$z_k=\sum_{i=0}{n-1}{y_i*(\omega_n{-k})^i}\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space$$
\]
\]
\]
\]
可以将$$\sum_{i=0}{n-1}\omega_n{i(j-k)}$$这部分看成一个首项为1,公比为\(\omega_n^{j-k}\)的等比数列,那么由等比数列求和公式可知:
当\(j-k\neq0\)时,$$\sum_{i=0}{n-1}\omega_n{i(j-k)}=\frac{(\omega_n{j-k})n-1}{\omega_n{j-k}-1}=\frac{(\omega_nn){j-k}-1}{\omega_n{j-k}-1}=\frac{(\omega_n0){j-k}-1}{\omega_n{j-k}-1}=\frac{1{j-k}-1}{\omega_n^{j-k}-1}=0$$
当\(j-k=0\)时,$$\sum_{i=0}{n-1}\omega_n{i(j-k)}=\sum_{i=0}{n-1}\omega_n{i0}=\sum_{i=0}^{n-1}1=n$$
这样就有$$z_k=a_k*n$$
\]
也就是说,IDFT相当于对当前多项式进行一次代入\(\omega_n^0,\omega_n^{-1},...,\omega_n^{-(n-1)}\)的DFT,再将每一项的系数除以n。
快速数论变化(FNTT)也是一个很多人选择背诵全文的算法。
只是把单位根换成了模意义下的原根而已
#include<algorithm>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define cd complex<double>
#define maxn 2000110
#define maxm (maxn<<1)
#define LL long long
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
const double pi=acos(-1);
const LL mod=998244353;
int n,m,r[maxm],len;
int a[maxm],b[maxm];
int mul(int x,int y)
{
int ans=1;
while(y)
{
if(y&1)ans=((LL)ans*(LL)x)%mod;
x=((LL)x*(LL)x)%mod,y>>=1;
}
return ans;
}
void fntt(int * c,double f)
{
rep(i,0,n-1)if(i<r[i])swap(c[i],c[r[i]]);
for(int i=1;i<n;i<<=1)
{
int wn=mul(3,(mod-1)/(i<<1)),x,y;
if(f==-1)wn=mul(wn,mod-2);
for(int j=0;j<n;j+=(i<<1))
{
int w=1;
rep(k,0,i-1)
x=c[j+k]%mod,y=((LL)w*(LL)c[j+i+k])%mod,c[j+k]=(x+y)%mod,c[j+i+k]=(x-y+mod)%mod,w=(LL)w*(LL)wn%mod;
}
}
}
int main()
{
n=read(),m=read();
rep(i,0,n)a[i]=read();
rep(i,0,m)b[i]=read();
m+=n;
for(n=1;n<m+1;n<<=1)len++;
rep(i,0,n-1)r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
fntt(a,1),fntt(b,1);
rep(i,0,n-1)a[i]=((LL)a[i]*(LL)b[i])%mod;
fntt(a,-1);int inv=mul(n,mod-2);
rep(i,0,m)printf("%d ",(LL)a[i]*(LL)inv%mod);
return 0;
}
并不对劲的DFT的更多相关文章
- 【算法•日更•第四十二期】离散傅里叶变换(DFT)
▎前言 小编相当的菜,这篇博客难度稍高,所以有些可能不会带有证明,博客中更多的是定义. 我们将要学到的东西: 复数 暴力多项式乘法 DFT 当然,小编之前就已经写过一篇博客了,主要讲的就是基础多项式, ...
- 转载:一幅图弄清DFT与DTFT,DFS的关系
转载:http://www.cnblogs.com/BitArt/archive/2012/11/24/2786390.html 很多同学学习了数字信号处理之后,被里面的几个名词搞的晕头转向,比如DF ...
- 频域分辨率与DFT,DCT,MDCT理解
搞了这么久音频算法,有些细节还没有很清楚. 比如DFT和DCT有哪些区别,DFT系数为什么会是对称的,同样帧长的数据,各自的频域分辨率是多少? 今天决定搞清楚这些问题, 首先DFT的系数对称(2N点的 ...
- 傅里叶:有关FFT,DFT与蝴蝶操作(转 重要!!!!重要!!!!真的很重要!!!!)
转载地址:http://blog.renren.com/share/408963653/15068964503(作者 : 徐可扬) 有没有!!! 其实我感觉这个学期算法最难最搞不懂的绝对不是动态规划 ...
- DFT basics
DFT测试中,最重要的部分还是sequential circuit的内部状态的测试. 起初ad hoc的方法用来提高testability,可以提高局部的coverage,但并不是一个系统性的方法. ...
- DFT设计绪论
DFT设计的主要目的是为了将defect-free的芯片交给客户. 产品质量,通常使用Parts Per million(PPM)来衡量. 但是随着IC从SSI到VLSI的发展,在test上花销的时间 ...
- FS,FT,DFS,DTFT,DFT,FFT的联系和区别
DCT变换的原理及算法 文库介绍 对于初学数字信号处理(DSP)的人来说,这几种变换是最为头疼的,它们是数字信号处理的理论基础,贯穿整个信号的处理. 学习过<高等数学>和<信号与系统 ...
- 【转】小解DCT与DFT
这学期当本科生数字图像处理的助教老师,为使学生更好地理解DCF和DFT之间的关系给出三题,大家可以思考一下,看一下自己对这些最简单的变换是否真正理解. 1.求解序列f(n)=[2,3,3,4,4,3, ...
- 【转】由DFT推导出DCT
原文地址:http://blog.sina.com.cn/s/blog_626631420100xvxd.htm 已知离散傅里叶变换(DFT)为: 由于许多要处理的信号都是实信号,在使用DFT时由于傅 ...
随机推荐
- [luoguP1783] 海滩防御(二分 || 最短路 || 最小生成树)
传送门 因为答案满足单调性,所以看到这个题,第一反应是二分,但是总是WA,也没有超时. 看了题解,,,,,, 这题刚开始很多人会想到二分,二分答案,然后看看是否能绕过所有信号塔,但是,这样写明显超时, ...
- [POJ1797] Heavy Transportation(最大生成树 || 最短路变形)
传送门 1.最大生成树 可以求出最大生成树,其中权值最小的边即为答案. 2.最短路 只需改变spfa里面的松弛操作就可以求出答案. ——代码 #include <queue> #inclu ...
- Codeforces396A - On Number of Decompositions into Multipliers
Portal Description 给出\(n(n\leq500)\)个\([1,10^9]\)的数,令\(m=\prod_{i=1}^n a_i\).求有多少个有序排列\(\{a_n\}\),使得 ...
- vue验证码点击更新
vue验证码点击更新 不说啥,直接贴代码 html: <img class="captcha" @click="editCaptcha" :src=&qu ...
- CPM、CPC、CPA、PFP、CPS、CPL、CPR介绍
一个网络媒体(网站)会包含有数十个甚至成千上万个页面,网络广告所投放的位置和价格 就牵涉到特定的页面以及浏览人数的多寡.这好比平面媒体(如报纸)的“版位”.“发行 量”,或者电波媒体(如电视)的“时段 ...
- 谈谈APP架构选型:React Native还是HBuilder
原文链接 导读:最近公司的一款新产品APP要进行研发,老大的意思想用H5来做混合APP以达到高效敏捷开发的目的.我自然就开始进行各种技术选型的调研,这里重点想说的是我最后挑选出的2款hybrid ap ...
- Codeforces 653D Delivery Bears【二分+网络流】
题目链接: http://codeforces.com/problemset/problem/653/D 题意: x个熊拿着相同重量的物品,从1号结点沿着路走到N号结点,结点之间有边相连,保证可以从1 ...
- freeswitch对媒体的处理的三种方式
一.默认方式:媒体通过freeswitch, RTP被freeswtich转发, freeswitch控制编码的协商并在协商不一致时提供语音编码转换能力, 支持录音,二次拨号等. 二.代理模式: ...
- Ubuntu 16.04安装Fiddler抓包工具(基于Mono,且会有BUG)
说明:Fiddler官方提供了Mono版本的,但是只有2014版本的,不是最新的,并且运行期间会有BUG,比如界面错乱卡死等等,但是勉强能代理,抓SSL的包,如果使用了要做好心理准备.将就一下还是可以 ...
- Maven新建webapp项目报错Could not resolve artifact org.apache.maven.archetypes:maven-archetype-webapp:pom:RELEASE
Windows-Preferences 在搜索框输入maven,点击下面的Archetypes--->Add Remote Catalog... 对应输入 http://repo1.maven. ...