多项式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意义下的逆元. 输入输出样例 输入样 ...
随机推荐
- 关于ckeditor在IE下出现不兼容的问题
今天在用ckeditor时在ie下测试出现了不兼容问题,样式,字体等属性设置不了. 后来在html标签上方添加了: <!DOCTYPE html PUBLIC "-//W3C//DTD ...
- /etc/passwd字段信息
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nol ...
- 外连接的用法 -- 《SQL进阶教程》 jupyter note
import pandas as pd import sqlite3 conn = sqlite3.connect('1-5.db') 用外连接进行行列转换1(行 -> 列): 制作交叉表 怎么 ...
- Springboot 上传报错: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: The multi-part request contained parameter data (excluding uploaded files) that exceede
Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: The ...
- 关于.Net Core+Angular+Ueditor富文本编辑器的使用方式
博客:https://www.cnblogs.com/24klr/ 资料:https://www.jianshu.com/p/0b21a1324d47 GitHub:https://github.co ...
- vue--vue-resource实现 get, post, jsonp请求
vue-resource 实现 get, post, jsonp请求 除了 vue-resource 之外,还可以使用 axios 的第三方包实现实现数据的请求 之前的学习中,如何发起数据请求? 常见 ...
- Windows编程中各种操作文件的方法
windows编程中文件操作有以下几种常见方法:1.C语言中文件操作.2.C++语言中的文件操作.3.Win32 API函数文件操作.4.MFC CFile类文件操作.5.MFC CFileDialo ...
- 第一次把mysql装进docker里碰到的各种问题
最近电脑经常关机要关好长时间,老是需要长按电源键强行关机.也不知道是怎么回事. 后来查看关机时的日志,发现是mysql停不掉.这可闹心了!怎么办?上网搜了搜也没有找到什么好的解决办法.总不能每次关机都 ...
- 升级降级(期望DP)2019 Multi-University Training Contest 7 hdu杭电多校第7场(Kejin Player)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6656 题意: 有 1~n 个等级,你现在是1级,求升到n级的花费期望.会给你n个条件(i~i+1级升级 ...
- python中format格式化函数
http://www.runoob.com/python/att-string-format.html