并不对劲的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时由于傅 ...
随机推荐
- xtu summer individual 2 C - Hometask
Hometask Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces. Origin ...
- zoj 2724 Windows Message Queue
Windows Message Queue Time Limit: 2 Seconds Memory Limit: 65536 KB Message queue is the basic f ...
- android GET 请求在5.0版本的取不到数据,报IO异常兼容问题解决
使用lib类库xUtils-2.6.10.jar作为数据请求的框架,在android的5.0版会有兼容问题,取不到GET请求的数据. 但是POST没有问题,难取到数据. public static R ...
- Eclipse安装插件长时间停留在calculating requirements and dependencies
如果安装插件的时候,Eclipse花费了很长的时间calculating requirements and dependencies(计算需求和依赖性 ) 这个问题通常就是在点击安装之后显示" ...
- spring security3.1升级到4.1问题(1)访问/j_spring_security_check 404
升级完后,发现登录不进去,把post改成get好了,但是系统的提交表单功能都不能用了,也是解决了很长时间,最后找到了根本原因. spring sercurity 4.0 csrf保护是默认开启的,cs ...
- 0c-适配 iOS 11
参考路径:https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653579210&idx=1&sn=d5ea8d46c ...
- Codeforces Round Edu 36
A.B.C 略 D(dfs+强连通分量) 题意: 给出一个n(n<=500)点m(m<=100000)边的有向图,问能否通过删去一条边使得该图无环. 分析: 最简单的想法就是枚举一条边删去 ...
- 转 asterisk app命令中文翻译
常规指令 Authenticate:鉴别用户 VMAuthenticate:根据“voicemail.conf”鉴别用户 Curl:接受外接URLs的修复.支持POSTing DUNDiLookup: ...
- 240.Search in a 2D Matrix II
/* * 240.Search in a 2D Matrix II * 2016-6-17by Mingyang * From left-bottom to right-top * 他这道题目虽说是用 ...
- SVN 更新后Tomcat 启动时出现问题
更新了svn后,启动本地的tomcat容器发现启动不了, 检查后发现是配置文件配置出现问题,因为我们的该项目 配置有tomcat与weblogic两种 , 而在我的web.xml中 默认配置的serv ...