多项式FFT/NTT模板(含乘法/逆元/log/exp/求导/积分/快速幂)
自己整理出来的模板
存在的问题:
1.多项式求逆常数过大(尤其是浮点数FFT)
2.log只支持f[0]=1的情况,exp只支持f[0]=0的情况
有待进一步修改和完善
FFT:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const db pi=acos(-);
const int N=4e5+,M=1e6+,mod=;
int n,m,n2,a[N];
int Pow(int x,int p) {
int ret=;
for(; p; p>>=,x=(ll)x*x%mod)if(p&)ret=(ll)ret*x%mod;
return ret;
}
struct P {
db x,y;
P operator+(const P& b) {return {x+b.x,y+b.y};}
P operator-(const P& b) {return {x-b.x,y-b.y};}
P operator*(const P& b) {return {x*b.x-y*b.y,x*b.y+y*b.x};}
P operator/(db b) {return {x/b,y/b};}
P cj() {return {x,-y};}
};
struct F_FT {
P A[N],B[N],w[N];
int b[N],c[N],d[N],e[N],f[N];
void FFT(P* a,int n,int f) {
for(int i=,j=n>>,k; i<n-; ++i,j^=k) {
if(i<j)swap(a[i],a[j]);
for(k=n>>; j&k; j^=k,k>>=);
}
for(int i=; i<n; ++i)w[i]= {cos(*pi*i/n),sin(*pi*i/n)};
for(int k=; k<n; k<<=)
for(int i=; i<n; i+=k<<)
for(int j=i; j<i+k; ++j) {
P W= {w[n//k*(j-i)].x,~f?w[n//k*(j-i)].y:-w[n//k*(j-i)].y};
P x=a[j],y=W*a[j+k];
a[j]=x+y,a[j+k]=x-y;
}
if(!~f)for(int i=; i<n; ++i)a[i]=a[i]/n;
}
void mul(int* a,int* b,int* c,int n) {
for(int i=; i<n; ++i)A[i]= {a[i]>>,a[i]&((<<)-)},B[i]= {b[i]>>,b[i]&((<<)-)},A[i+n]= {,},B[i+n]= {,};
n<<=;
FFT(A,n,),FFT(B,n,);
for(int i=; i<=n/; ++i) {
int j=(n-i)&(n-);
P a1=(A[i]+A[j].cj())* (P) {0.5,},b1=(A[i]-A[j].cj())* (P) {,-0.5};
P a2=(B[i]+B[j].cj())* (P) {0.5,},b2=(B[i]-B[j].cj())* (P) {,-0.5};
P a3=(A[j]+A[i].cj())* (P) {0.5,},b3=(A[j]-A[i].cj())* (P) {,-0.5};
P a4=(B[j]+B[i].cj())* (P) {0.5,},b4=(B[j]-B[i].cj())* (P) {,-0.5};
A[i]=a1*a2+b1*b2* (P) {,},B[i]=a1*b2+a2*b1;
A[j]=a3*a4+b3*b4* (P) {,},B[j]=a3*b4+a4*b3;
}
FFT(A,n,-),FFT(B,n,-);
for(int i=; i<n; ++i)c[i]=(((ll(A[i].x+0.5)%mod)<<)+ll(A[i].y+0.5)+(ll(B[i].x+0.5)<<))%mod;
}
void inverse(int* a,int n) {
for(int i=; i<n; ++i)b[i]=;
b[]=Pow(a[],mod-);
for(int m=; m<=n; m<<=) {
mul(b,b,c,m),mul(a,c,c,m);
for(int i=; i<m; ++i)b[i]=(((ll)b[i]*-c[i])%mod+mod)%mod;
}
for(int i=; i<n; ++i)a[i]=b[i];
}
void der(int* a,int n) {for(int i=; i<n; ++i)a[i-]=(ll)i*a[i]%mod; a[n-]=;}
void itg(int* a,int n) {for(int i=n-; i>=; --i)a[i+]=(ll)Pow(i+,mod-)*a[i]%mod; a[]=;}
void log(int* a,int n) {
for(int i=; i<n; ++i)d[i]=a[i];
inverse(d,n),der(a,n),mul(a,d,a,n),itg(a,n);
}
void exp(int* a,int n) {
for(int i=; i<n; ++i)e[i]=;
e[]=;
for(int m=; m<=n; m<<=) {
for(int i=; i<m; ++i)f[i]=e[i];
log(f,m);
for(int i=; i<m; ++i)f[i]=(a[i]-f[i]+mod)%mod;
f[]++;
mul(e,f,e,m);
}
for(int i=; i<n; ++i)a[i]=e[i];
}
void pow(int* a,int n,int p) {
int j=;
for(; j<n&&!a[j]; ++j);
if(j==n)return;
int px=Pow(a[j],p),invx=Pow(a[j],mod-);
for(int i=j; i<n; ++i)a[i-j]=(ll)a[i]*invx%mod;
for(int i=n-j; i<n; ++i)a[i]=;
log(a,n);
for(int i=; i<n; ++i)a[i]=(ll)a[i]*p%mod;
exp(a,n);
for(int i=n-; i>=(ll)j*p; --i)a[i]=(ll)a[i-j*p]*px%mod;
for(int i=; i<n&&i<(ll)j*p; ++i)a[i]=;
}
} fft;
int main() {
scanf("%d%d",&n,&m);
for(int i=; i<n; ++i)scanf("%d",&a[i]),a[i]%=mod;
for(n2=; n2<n; n2<<=);
fft.pow(a,n2,m);
for(int i=; i<n; ++i)printf("%d%c",a[i]," \n"[i==n-]);
return ;
}
NTT:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+,M=1e6+,mod=;
const int G=;
int n,m,n2,a[N];
int Pow(int x,int p) {
int ret=;
for(; p; p>>=,x=(ll)x*x%mod)if(p&)ret=(ll)ret*x%mod;
return ret;
}
struct F_FT {
int A[N],B[N],b[N],c[N],d[N],e[N],f[N];
void FFT(int* a,int n,int f) {
for(int i=,j=n>>,k; i<n-; ++i,j^=k) {
if(i<j)swap(a[i],a[j]);
for(k=n>>; j&k; j^=k,k>>=);
}
for(int k=; k<n; k<<=) {
int gn=Pow(G,(mod-)/(k<<));
if(f==-)gn=Pow(gn,mod-);
for(int i=; i<n; i+=k<<) {
int g=;
for(int j=i; j<i+k; ++j,g=(ll)g*gn%mod) {
int x=a[j],y=(ll)g*a[j+k]%mod;
a[j]=((ll)x+y)%mod,a[j+k]=((ll)x-y+mod)%mod;
}
}
}
if(!~f) {
int invn=Pow(n,mod-);
for(int i=; i<n; ++i)a[i]=(ll)a[i]*invn%mod;
}
}
void mul(int* a,int* b,int* c,int n) {
for(int i=; i<n; ++i)A[i]=a[i],B[i]=b[i],A[i+n]=B[i+n]=;
n<<=;
FFT(A,n,),FFT(B,n,);
for(int i=; i<n; ++i)c[i]=(ll)A[i]*B[i]%mod;
FFT(c,n,-);
}
void inverse(int* a,int n) {
for(int i=; i<n; ++i)b[i]=;
b[]=Pow(a[],mod-);
for(int m=; m<=n; m<<=) {
for(int i=; i<m; ++i)A[i]=a[i],B[i]=b[i],A[i+m]=B[i+m]=;
FFT(A,m<<,),FFT(B,m<<,);
for(int i=; i<(m<<); ++i)b[i]=(((ll)B[i]*-(ll)A[i]*B[i]%mod*B[i]%mod)%mod+mod)%mod;
FFT(b,m<<,-);
for(int i=m; i<(m<<); ++i)b[i]=;
}
for(int i=; i<n; ++i)a[i]=b[i];
}
void der(int* a,int n) {for(int i=; i<n; ++i)a[i-]=(ll)i*a[i]%mod; a[n-]=;}
void itg(int* a,int n) {for(int i=n-; i>=; --i)a[i+]=(ll)Pow(i+,mod-)*a[i]%mod; a[]=;}
void log(int* a,int n) {
for(int i=; i<n; ++i)d[i]=a[i];
inverse(d,n),der(a,n),mul(a,d,a,n),itg(a,n);
}
void exp(int* a,int n) {
for(int i=; i<n; ++i)e[i]=;
e[]=;
for(int m=; m<=n; m<<=) {
for(int i=; i<m; ++i)f[i]=e[i];
log(f,m);
for(int i=; i<m; ++i)f[i]=(a[i]-f[i]+mod)%mod;
f[]++;
mul(e,f,e,m);
}
for(int i=; i<n; ++i)a[i]=e[i];
}
void pow(int* a,int n,int p) {
int j=;
for(; j<n&&!a[j]; ++j);
if(j==n)return;
int px=Pow(a[j],p),invx=Pow(a[j],mod-);
for(int i=j; i<n; ++i)a[i-j]=(ll)a[i]*invx%mod;
for(int i=n-j; i<n; ++i)a[i]=;
log(a,n);
for(int i=; i<n; ++i)a[i]=(ll)a[i]*p%mod;
exp(a,n);
for(int i=n-; i>=(ll)j*p; --i)a[i]=(ll)a[i-j*p]*px%mod;
for(int i=; i<n&&i<(ll)j*p; ++i)a[i]=;
}
} fft;
int main() {
scanf("%d%d",&n,&m);
for(int i=; i<n; ++i)scanf("%d",&a[i]),a[i]%=mod;
for(n2=; n2<n; n2<<=);
fft.pow(a,n2,m);
for(int i=; i<n; ++i)printf("%d%c",a[i]," \n"[i==n-]);
return ;
}
代码源自洛谷P4238
多项式FFT/NTT模板(含乘法/逆元/log/exp/求导/积分/快速幂)的更多相关文章
- 洛谷 P3811 【模板】乘法逆元
P3811 [模板]乘法逆元 题目背景 这是一道模板题 题目描述 给定n,p求1~n中所有整数在模p意义下的乘法逆元. 输入输出格式 输入格式: 一行n,p 输出格式: n行,第i行表示i在模p意义下 ...
- 多项式FFT相关模板
自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h& ...
- P3811 【模板】乘法逆元
P3811 [模板]乘法逆元 线性递推逆元模板 #include<iostream> #include<cstdio> #include<cstring> #def ...
- [洛谷P3811]【模板】乘法逆元
P3811 [模板]乘法逆元 题意 求1-n所有整数在模p意义下的逆元. 分析 逆元 如果x满足\(ax=1(\%p)\)(其中a p是给定的数)那么称\(x\)是在\(%p\)意义下\(a\)的逆元 ...
- 模板【洛谷P3811】 【模板】乘法逆元
P3811 [模板]乘法逆元 给定n,p求1~n中所有整数在模p意义下的乘法逆元. T两个点的费马小定理求法: code: #include <iostream> #include < ...
- 洛谷——P3811 【模板】乘法逆元
P3811 [模板]乘法逆元 线性求逆元 逆元定义:若$a*x\equiv1 (\bmod {b})$,且$a$与$b$互质,那么我们就能定义: $x$为$a$的逆元,记为$a^{-1}$,所以我们也 ...
- 题解 P3811 【【模板】乘法逆元】
P3811 [模板]乘法逆元 一个刚学数论的萌新,总结了一下这题的大部分做法 //一.费马小定理+快速幂 O(nlogn) 64分 #include<cstdio> using names ...
- 逆元-P3811 【模板】乘法逆元-洛谷luogu
https://www.cnblogs.com/zjp-shadow/p/7773566.html -------------------------------------------------- ...
- luogu P3811 【模板】乘法逆元
题目背景 这是一道模板题 题目描述 给定n,p求1~n中所有整数在模p意义下的乘法逆元. 输入输出格式 输入格式: 一行n,p 输出格式: n行,第i行表示i在模p意义下的逆元. 输入输出样例 输入样 ...
随机推荐
- vscode 配置 GOPATH
我已经放弃goland开发工具了,所以用万能的vscode 作为我学习go的开始: 按照网上的教程一步步配置了GOROOT,GOPATH等等,执行go env 也是没有问题的,但是当我用vscode写 ...
- vuejs与angularjs以及react的区别?
1.与AngularJS的区别 相同点: 都支持指令:内置指令和自定义指令. 都支持过滤器:内置过滤器和自定义过滤器. 都支持双向数据绑定. 都不支持低端浏览器. 不同点: 1.AngularJS的学 ...
- Day05:集合操作——线性表(二) / 查找表 / 文件操作——File(一)
文件操作:https://www.cnblogs.com/wsnb8/p/11403626.html
- webdriervAPI(元素等待)
from selenium import webdriver from selenium.common.exceptions import NoSuchElementException driv ...
- 【Python】【demo实验2】【打印乘法口诀表】
打印乘法口诀表 源代码: # encoding=utf-8 for i in range(1,10): print("\n") for j in range(1,10): if i ...
- Git的常见操作
1.git init:初始化 git status:查看版本状态 git log : 查看提交日志
- 与C++开启新路途
1.我与C的过去 学习C语言大概是从18年8月开始,一直到19年3月.我完成了对C的基本认识和学习,也顺利通过了二级C计算机的考试.不过当你开始深入于C的世界时,你会发现学习的基础好像略有浅薄.宏的世 ...
- Luogu P4118 [Ynoi2016]炸脖龙I
题目 首先考虑没有修改的情况.显然直接暴力扩展欧拉定理就行了,单次复杂度为\(O(\log p)\)的. 现在有了修改,我们可以树状数组维护差分数组,然后\(O(\log n)\)地单次查询单点值. ...
- python-优酷系统管理员视图粗糙版(无详细注释)
目录 Tank-YouKu(仅管理员功能粗糙版) 优酷系统管理员视图功能 前期准备 创库创表语句 安装pymysql模块 安装DBUtils模块 配置 db_pool 项目架构与数据流向 目录结构 s ...
- SSM和Spring Boot常用配置比较
一.Dao层相关 1.Mysql相关: 1.1配置DataSource连接池: (1)SSM配置: <!-- 加密后配置自己写的解析文件 --> <bean class=" ...