多项式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意义下的逆元. 输入输出样例 输入样 ...
随机推荐
- mybatis-generator自动生成代码时,只生成insert方法
今天使用mybatis-generator自动生成代码时,发现只能生成insert方法, 以前所有的方法都是可以生成的,查看网上解决办法和检查数据库表结构后, 发现2种可以解决的办法: 1.修改myb ...
- axios在Vue中的简单应用(一)
1.安装axios: npm install --save axios vue-axios 2.安装qs: qs.stringify(data)可以解决data数据格式问题 npm install - ...
- java安全停止线程
Thread.stop()是一个被废弃的方法,不被推荐使用的原因是stop方法太过于暴力,强行把执行到一半的线程终止,并且会立即释放这个线程所有的锁.会破坏了线程中引用对象的一致性. 使用判断标志位的 ...
- android webview 添加内置对象
package com.android.EBrowser; import android.app.Activity;import android.graphics.Rect;import androi ...
- 关于content的理解
Context字面意思上下文,位于framework packageandroid.content.Context中,其实该类为long型,类似Win32中的Handle句柄,很多方法需要通过 Con ...
- selenium—alert用法
切换到弹框: switch_to_alert() ① alert.accept() 确认弹框 driver.switch_to_alert().accept() ② alert.dismiss() ...
- MSF魔鬼训练营-3.5.3 MSF中常用的关于数据库的命令
渗透测试数据库用来保存渗透测试过程中获取的各种数据,很多时候你重启了kali发现连接不上数据库了,其实就是因为这个服务没开 MSF所使用的数据库时postgresql root@kali:/# ser ...
- 如何解决Oracle11g使用dmp命令无法导出空表问题
如何解决Oracle11g使用dmp命令无法导出空表问题 导出:exp username/password@orcl file=路径 tables=(tb1) //tables=(tb1)可有 ...
- opencv学习之读取图像-imread函数
序 想要完整全面地学习opencv,仅凭阅读samples的示例源码是不够的.毕竟opencv是一个拥有非常多函数的程序库,所以在每学习一个函数时,芒果觉得有必要记录下来,分享给有需要的同学.于是,就 ...
- Java设计模式七种写法
懒汉模式-线程不安全 public class Singleton { private static Singleton instance; private Singleton (){ } publi ...