FFT&NTT学习笔记
具体原理就不讲了qwq,毕竟证明我也不太懂
FFT(快速傅立叶变换)&NTT(快速数论变换)
FFT
//求多项式乘积
//要求多项式A和多项式B的积多项式C
//具体操作就是
//DFT(A),DFT(B)->暴力乘积->拉格朗日插值(即IDFT(C))->C
//其中DFT表示离散傅里叶变换
//通俗的来说就是用点值表示多项式
//使用神秘单位复数根将时间复杂度降至O(nlogn)
//ps:但是常数巨大
//pps:应用非常广泛,非常多题目都要fft or ntt优化,板子一定要背熟
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define pw(n) (1<<n)
using namespace std;
const double pi=acos(-);
struct complex{
double a,b;
complex(double _a=,double _b=){
a=_a;
b=_b;
}
friend complex operator +(complex x,complex y){return complex(x.a+y.a,x.b+y.b);}
friend complex operator -(complex x,complex y){return complex(x.a-y.a,x.b-y.b);}
friend complex operator *(complex x,complex y){return complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);}
friend complex operator *(complex x,double y){return complex(x.a*y,x.b*y);}
friend complex operator /(complex x,double y){return complex(x.a/y,x.b/y);}
}a[],b[];
int n,m,bit,bitnum=,rev[pw()];
void getrev(int l){//Reverse
for(int i=;i<pw(l);i++){
rev[i]=(rev[i>>]>>)|((i&)<<(l-));
}
}
void FFT(complex *s,int op){
for(int i=;i<bit;i++)if(i<rev[i])swap(s[i],s[rev[i]]);
for(int i=;i<bit;i<<=){
complex w(cos(pi/i),op*sin(pi/i));
for(int p=i<<,j=;j<bit;j+=p){//Butterfly
complex wk(,);
for(int k=j;k<i+j;k++,wk=wk*w){
complex x=s[k],y=wk*s[k+i];
s[k]=x+y;
s[k+i]=x-y;
}
}
}
if(op==-){
for(int i=;i<=bit;i++){
s[i]=s[i]/(double)bit;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lf",&a[i].a);
for(int i=;i<=m;i++)scanf("%lf",&b[i].a);
m+=n;
for(bit=;bit<=m;bit<<=)bitnum++;
getrev(bitnum);
FFT(a,);
FFT(b,);
for(int i=;i<=bit;i++)a[i]=a[i]*b[i];
FFT(a,-);
for(int i=;i<=m;i++)printf("%d ",(int)(a[i].a+0.5));
return ;
}
NTT
//费马数数论变换
//大家觉得998244353好还是1004535809好?^_^
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define pw(n) (1<<n)
using namespace std;
const int N=,P=,g=;//或P=1004535809
int n,m,bit,bitnum=,a[N+],b[N+],rev[N+];
void getrev(int l){
for(int i=;i<pw(l);i++){
rev[i]=(rev[i>>]>>)|((i&)<<(l-));
}
}
int fastpow(int a,int b){
int ans=;
for(;b;b>>=,a=1LL*a*a%P){
if(b&)ans=1LL*ans*a%P;
}
return ans;
}
void NTT(int *s,int op){
for(int i=;i<bit;i++)if(i<rev[i])swap(s[i],s[rev[i]]);
for(int i=;i<bit;i<<=){
int w=fastpow(g,(P-)/(i<<));
for(int p=i<<,j=;j<bit;j+=p){
int wk=;
for(int k=j;k<i+j;k++,wk=1LL*wk*w%P){
int x=s[k],y=1LL*s[k+i]*wk%P;
s[k]=(x+y)%P;
s[k+i]=(x-y+P)%P;
}
}
}
if(op==-){
reverse(s+,s+bit);
int inv=fastpow(bit,P-);
for(int i=;i<bit;i++)a[i]=1LL*a[i]*inv%P;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=m;i++)scanf("%d",&b[i]);
m+=n;
for(bit=;bit<=m;bit<<=)bitnum++;
getrev(bitnum);
NTT(a,);
NTT(b,);
for(int i=;i<bit;i++)a[i]=1LL*a[i]*b[i]%P;
NTT(a,-);
for(int i=m;i>=;i--)printf("%d ",a[i]);
return ;
}
FFT&NTT学习笔记的更多相关文章
- FFT/NTT 学习笔记
0. 前置芝士 基础群论 复数 \(\mathbb C = \mathbb R[x^2+1]\) 则有 \(i^2+1=(-i)^2+1=0\),\(i \in \mathbb C - \mathbb ...
- FFT和NTT学习笔记_基础
FFT和NTT学习笔记 算法导论 参考(贺) http://picks.logdown.com/posts/177631-fast-fourier-transform https://blog.csd ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅲ
第三波,走起~~ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ 单位根反演 今天打多校时 1002 被卡科技了 ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ
众所周知,tzc 在 2019 年(12 月 31 日)就第一次开始接触多项式相关算法,可到 2021 年(1 月 1 日)才开始写这篇 blog. 感觉自己开了个大坑( 多项式 多项式乘法 好吧这个 ...
- FFT、NTT学习笔记
参考资料 picks miskcoo menci 胡小兔 unname 自为风月马前卒 上面是FFT的,学完了就来看NTT吧 原根 例题:luogu3803 fft优化后模板 #include < ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ
因为垃圾电脑太卡了就重开了一个... 前传:多项式Ⅰ u1s1 我预感还会有Ⅲ 多项式基础操作: 例题: 26. CF438E The Child and Binary Tree 感觉这题作为第一题还 ...
- 快速傅里叶变换(FFT)学习笔记(未完待续)
目录 参考资料 FFT 吹水 例题 普通做法 更高大尚的做法 定义与一部分性质 系数表达式 点值表达式 点值相乘??? 卷积 复数 单位根 DFT IDFT 蝴蝶迭代优化 单位根求法 实现.细节与小优 ...
- NTT学习笔记
和\(FFT\)相对应的,把单位根换成了原根,把共轭复数换成了原根的逆元,最后输出的时候记得乘以原\(N\)的逆元即可. #include <bits/stdc++.h> using na ...
- NTT 学习笔记
引入 \(\tt NTT\) 和 \(\tt FFT\) 有什么不一样呢? 就是 \(\tt NTT\) 是可以用来取模的,而且没有复数带来的精度误差. 最最重要的是据说 \(\tt NTT\) 常数 ...
随机推荐
- day16 闭包以及装饰器(好东西)
目录 闭包 装饰器 最基础的装饰器 完善装饰器 有返回值的 有参数的 装饰器模版 语法糖 登录装饰器 可变类型的局部变量可以修改全局变量 三层装饰器 闭包 首先要理解函数对象的概念,其实函数名就相当于 ...
- Python-超好用的Django源码解析
http://djangobook.py3k.cn/2.0/
- 查看系统进程:ps、top
1.ps命令:提供最近进程的快照.显示当前活跃进程的简要信息. 常见使用: (1)与grep命令配合查找是否有相应进程存活 ps -ef | grep ksmd ps -Af | grep ksmd ...
- WebService 布置简单的计算器
实验环境:myeclipse2015 具体的过程如下: 首先建立一个web service project 命名就为WebServiceProject,同时选择web service framewor ...
- sql查询语句中on和where的区别
sql中的连接查询分为3种, cross join,inner join,和outer join , 在 cross join和inner join中,筛选条件放在on后面还是where后面是没区别 ...
- 2015 Multi-University Training Contest 6 hdu 5361 In Touch
In Touch Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total ...
- 2 怎样解析XML文件或字符串
1 引用XML文件 2 使用XMLReader解析文本字符串 3 使用XMLReader方法读取XML数据 详细代码实现例如以下: //初始化一个XML字符串 String xmlString = @ ...
- BZOJ 1007: [HNOI2008]水平可见直线 平面直线
1007: [HNOI2008]水平可见直线 Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则 ...
- 当我们谈论Erlang Maps时,我们谈论什么 Part 2
声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.兴许Maps可能会出现语法或函数API上的有所调整,特此说明. 前情提要: [Erlang 0116] 当我们谈论E ...
- 英特尔深度学习框架BigDL——a distributed deep learning library for Apache Spark
BigDL: Distributed Deep Learning on Apache Spark What is BigDL? BigDL is a distributed deep learning ...