【FFT】学习笔记
首先,多项式有两种表示方式,系数表示和点值表示
对于两个多项式相乘而言,用系数表示进行计算是O(n^2)的
而用点值表示进行计算是O(n)的
那么我们自然就会去想如果把系数表示的多项式转化为点值表示的多项式进行计算,不就可以减少时间复杂度了么
然而,一般情况下系数表示的多项式想要转化成点值表示的多项式,或是点值表示的多项式想要转化成系数表示的多项式,复杂度都是O(n^2)的
但这只是一般情况
我们可以通过取特殊值把系数表示转化成点值表示,这样的话能把复杂度降到O(nlogn),这就是DFT了
同样通过求逆之类的操作可以把点值表示转换为系数表示,同样复杂度为O(nlogn),这就是IDFT了
嘛。。。
简单来说就是这样的吧
代码
//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define mpr make_pair
#define maxn 200005
#define inf (1<<30)
#define eps 1e-8
#define pi 3.1415926535897932384626
using namespace std; inline int read()
{
int ret=;bool fla=;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-'){fla=;ch=getchar();}
while(ch>=''&&ch<=''){ret=ret*+ch-'';ch=getchar();}
return fla?-ret:ret;
} struct cp{
db x,y;
}A[maxn],B[maxn],C[maxn],D[maxn]; int n,m,mx,len,rev[maxn],a[maxn],cnt[maxn]; cp operator + (const cp &x,const cp &y){return (cp){x.x+y.x,x.y+y.y};}
cp operator - (const cp &x,const cp &y){return (cp){x.x-y.x,x.y-y.y};}
cp operator * (const cp &x,const cp &y){return (cp){x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x};} void FFT(cp *a,int op)
{
for(int i=;i<n;++i) if(rev[i]>i) swap(a[i],a[rev[i]]);
for(int k=;k<n;k<<=)
{
cp omi=(cp){cos(pi/k),sin(pi/k)*op};
for(int i=;i<n;i+=(k<<))
{
cp w=(cp){1.0,0.0};
for(int j=;j<k;++j,w=w*omi)
{
cp x=a[i+j],y=a[i+j+k]*w;
a[i+j]=x+y,a[i+j+k]=x-y;
}
}
}
if(op==-) for(int i=;i<n;++i) a[i].x/=n;
} int main()
{
n=read();
for(int i=,x;i<=n;++i) x=read(),mx=max(mx,*x),A[x].x=,B[x*].x=,C[x*].x=;
m=mx;
for(n=;n<=m;n<<=) len++;
for(int i=;i<n;++i) rev[i]=(rev[i>>]>>)|((i&)<<(len-));
FFT(A,);FFT(B,),FFT(C,);
for(int i=;i<n;++i)
{
cp tmp1=(cp){1.0/6.0,};
cp tmp2=(cp){3.0,};
cp tmp3=(cp){2.0,};
cp tmp4=(cp){1.0/2.0,};
D[i]=(A[i]*A[i]*A[i]-tmp2*B[i]*A[i]+tmp3*C[i])*tmp1;
D[i]=D[i]+(A[i]*A[i]-B[i])*tmp4;
D[i]=D[i]+A[i];
}
FFT(D,-);
for(int i=;i<n;++i)
{
int pri=(int)(D[i].x+0.5);
if(pri>) printf("%d %d\n",i,pri);
}
return ;
}
【FFT】学习笔记的更多相关文章
- 快速傅里叶变换(FFT)学习笔记
定义 多项式 系数表示法 设\(A(x)\)表示一个\(n-1\)次多项式,则所有项的系数组成的\(n\)维向量\((a_0,a_1,a_2,\dots,a_{n-1})\)唯一确定了这个多项式. 即 ...
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
- 快速傅里叶变换(FFT)学习笔记(其一)
再探快速傅里叶变换(FFT)学习笔记(其一) 目录 再探快速傅里叶变换(FFT)学习笔记(其一) 写在前面 为什么写这篇博客 一些约定 前置知识 多项式卷积 多项式的系数表达式和点值表达式 单位根及其 ...
- 快速傅里叶变换(FFT)学习笔记(其二)(NTT)
再探快速傅里叶变换(FFT)学习笔记(其二)(NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其二)(NTT) 写在前面 一些约定 前置知识 同余类和剩余系 欧拉定理 阶 原根 求原根 NTT ...
- 口胡FFT现场(没准就听懂了)&&FFT学习笔记
前言(不想听的可以跳到下面) OK.蒟蒻又来口胡了. 自从ZJOI2019上Day的数论课上的多项式听到懵逼了,所以我就下定决心要学好多项式.感觉自己以前学的多项式都是假的. 但是一直在咕咕,现在是中 ...
- 【笔记篇】(理论向)快速傅里叶变换(FFT)学习笔记w
现在真是一碰电脑就很颓废啊... 于是早晨把电脑锁上然后在旁边啃了一节课多的算导, 把FFT的基本原理整明白了.. 但是我并不觉得自己能讲明白... Fast Fourier Transformati ...
- FFT学习笔记
快速傅里叶变换FFT(Fast Fourior Transform) 先说一下它能干嘛qwq 傅里叶变换有两种,连续傅里叶变换和离散傅里叶变换,OI中主要用来快速计算多项式卷积. 等一下,卷积是啥 ...
- 多项式乘法(FFT)学习笔记
------------------------------------------本文只探讨多项式乘法(FFT)在信息学中的应用如有错误或不明欢迎指出或提问,在此不胜感激 多项式 1.系数表示法 ...
- 【文文殿下】快速傅里叶变换(FFT)学习笔记
多项式 定义 形如\(A(x)=\sum_{i=0}^{n-1} a_i x^i\)的式子称为多项式. 我们把\(n\)称为该多项式的次数界. 显然,一个\(n-1\)次多项式的次数界为\(n\). ...
- 分治 FFT学习笔记
先给一道luogu板子题:P4721 [模板]分治 FFT 今天模拟有道题的部分分做法是分治fft,于是就学了一下.感觉不是很难,国赛上如果推出式子的话应该能写出来. 分治fft用来解决这么一个式子\ ...
随机推荐
- codeforecs Gym 100286B Blind Walk
交互式程序,要用到一个函数fflush,它的作用是对标准输出流的清理,对stdout来说是及时地打印数据到屏幕上,一个事实:标准输出是以『行』为单位进行的,也即碰到\n才打印数据到屏幕.这就可能造成延 ...
- ArrayList 源码分析(JDK1.8)
ArrayList简介 ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess ...
- Oracle中ROWID详解
oracle数据库的表中的每一行数据都有一个唯一的标识符,或者称为rowid,在oracle内部通常就是使用它来访问数据的.rowid需要 10个字节的存储空间,并用18个字符来显示.该值表明了该行在 ...
- JS给数字加千位分隔符
本文原链接:https://www.jianshu.com/p/928c68f92c0c JavaScript实现千位分隔符 将普通的数字转换为带千位分隔符格式的数字字符串是一个非常常见的问题,千位分 ...
- 在DataGridView控件中显示下拉列表
实现效果: 知识运用: DataGridViewComboBoxColumn类 //通过该类可以创建下拉列表样式的列 实现代码: private void Form1_Load(object send ...
- CMDB API验证
CMDB API验证 为什么做API验证 API验证是防止数据在传输的过程中,保证数据不被篡改 如何设计的API验证 灵感来源于Torando中加密Cookie的源码,主要是生成加密的随机字符串. M ...
- LeetCode935
问题:935. 骑士拨号器 国际象棋中的骑士可以按下图所示进行移动: . 这一次,我们将 “骑士” 放在电话拨号盘的任意数字键(如上图所示)上,接下来,骑士将会跳 N-1 步. ...
- STA basic
- 14-15.Yii2.0模型的创建/读取数据使用,框架防止sql注入
目录 创建数据库 表article 配置 db.php 连接数据库 创建控制器 HomeController.php 创建models 创建数据库 表article 1.创建库表 CREATE TAB ...
- python之自定义排序函数sorted()
sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面, ...