FFT&NTT模板

博主菜鸡,只会背模板,根本解释不来嘤嘤嘤~

FFT:

#include<bits/stdc++.h>
#define IL inline
#define LF double
using namespace std;
const int N=5e6+5;
const LF Pi=acos(-1.0);
struct com{
    LF x,y;
    com(LF xx=0,LF yy=0){x=xx,y=yy;}
    com operator+(const com &a) const{return com(a.x+x,a.y+y);}
    com operator-(const com &a) const{return com(x-a.x,y-a.y);}
    com operator*(const com &a) const{return com(x*a.x-y*a.y,a.x*y+a.y*x);}
}a[N],b[N];
IL int in(){
    char c;int f=1;
    while((c=getchar())<‘0‘||c>‘9‘)
      if(c==‘-‘) f=-1;
    int x=c-‘0‘;
    while((c=getchar())>=‘0‘&&c<=‘9‘)
      x=x*10+c-‘0‘;
    return x*f;
}
int n,m,r[N],Max=1,cnt;
void FFT(com *a,int op){
    for(int i=0;i<Max;++i) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=1;i<Max;i<<=1){
        com Wn=com(cos(Pi/i),op*sin(Pi/i));
        for(int k=i<<1,j=0;j<Max;j+=k){
            com w=com(1,0);
            for(int l=0;l<i;++l,w=w*Wn){
                com x=a[j+l],y=w*a[j+i+l];
                a[j+l]=x+y,a[j+i+l]=x-y;
            }
        }
    }
}
int main()
{
    n=in(),m=in();
    while(Max<=n+m) Max<<=1,++cnt;
    for(int i=0;i<Max;++i) r[i]=(r[i>>1]>>1)|((i&1)<<cnt-1);
    for(int i=0;i<=n;++i) a[i].x=in();
    for(int i=0;i<=m;++i) b[i].x=in();
    FFT(a,1),FFT(b,1);
    for(int i=0;i<=Max;++i) a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=0;i<=n+m;++i) printf("%d ",(int)(a[i].x/Max+0.5));
    return 0;
}

NTT:

#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const LL P=998244353,G=3,Gi=332748118,N=4e6+3;
LL n,m,a[N],b[N];
int r[N],Max=1,cnt;
IL int in(){
    char c;int f=1;
    while((c=getchar())<‘0‘||c>‘9‘)
      if(c==‘-‘) f=-1;
    int x=c-‘0‘;
    while((c=getchar())>=‘0‘&&c<=‘9‘)
      x=x*10+c-‘0‘;
    return x*f;
}
IL LL ksm(LL a,LL b){
    LL c=1;
    while(b){
        if(b&1) c=c*a%P;a=a*a%P;
        b>>=1;
    }
    return c;
}
void NTT(LL *a,int op){
    for(int i=0;i<Max;++i) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=1;i<Max;i<<=1){
        LL wn=ksm(~op?G:Gi,(P-1)/(i<<1));
        for(int j=0;j<Max;j+=(i<<1)){
            LL w=1;
            for(int k=0;k<i;++k,w=wn*w%P){
                LL x=a[j+k],y=w*a[j+i+k]%P;
                a[j+k]=(x+y)%P,a[j+i+k]=(x-y+P)%P;
            }
        }
    }
}
int main()
{
    n=in(),m=in();
    for(int i=0;i<=n;++i) a[i]=(in()+P)%P;
    for(int i=0;i<=m;++i) b[i]=(in()+P)%P;
    while(Max<=n+m) Max<<=1,++cnt;
    for(int i=0;i<Max;++i) r[i]=(r[i>>1]>>1)|((i&1)<<cnt-1);
    NTT(a,1),NTT(b,1);
    for(int i=0;i<Max;++i) a[i]=a[i]*b[i]%P;NTT(a,-1);
    LL inv=ksm(Max,P-2);
    for(int i=0;i<=n+m;++i) printf("%lld ",(a[i]*inv)%P);
    return 0;
}

原文地址:https://www.cnblogs.com/yiqiAtiya/p/12069456.html

时间: 2024-08-01 06:12:00

FFT&NTT模板的相关文章

多项式FFT/NTT模板(含乘法/逆元/log/exp/求导/积分/快速幂)

自己整理出来的模板 存在的问题: 1.多项式求逆常数过大(尤其是浮点数FFT) 2.log只支持f[0]=1的情况,exp只支持f[0]=0的情况 有待进一步修改和完善 FFT: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 const db pi=acos(-1); 6 const int N=4e5+10,M=1e6+10,mod=9982443

分治FFT/NTT 模板

题目要我们求$f[i]=\sum\limits_{j=1}^{i}f[i-j]g[j]\;mod\;998244353$ 直接上$NTT$肯定是不行的,我们不能利用尚未求得的项卷积 所以要用$CDQ$分治,先递归$[l,mid]$,然后处理$[l,mid]$对$[mid+1,r]$的影响,再递归$[mid+1,r]$ 当我们处理$[l,mid]$对$[mid+1,r]$的影响时,$f[i](i\in [l,mid])$的是已经求完的,所以能用$NTT$卷积 细节比较多,注意不要让$f[i](i\

FFT/NTT做题方法与调试技巧(+提高码题效率的一些想法)

(其实本文应该写成了"结合FFT讨论的调试技巧+码题方法",语文不好一写文章就偏题QAQ) 有意见欢迎提出,有遗漏欢迎补充! FFT(快速傅里叶变换)/NTT(数论变换)是卷积运算常见而实用的优化 但是FFT/NTT的处理过程并不像暴力运算(差不多是多项式乘法)那样能够直观地反映卷积结果的实时变化. 因此在使用FFT时将会或多或少地加大调试的难度. 如果调试程序时直接跟踪变量,每步手算结果比对,不仅会耽误大量时间,而且效果可能并不理想. 直接肉眼查错效率可能也不太高. 但也正由于FFT

FFT快速傅里叶模板

FFT快速傅里叶模板-- /* use way: assign : h(x) = f(x) * g(x) f(x):len1 g(x):len2 1. len = 1; while(len < 2 * len1 || len < 2 * len2) len <<= 1; 2. for i=0 to len1-1 : x1[i](f(i),0) for i=len1 to len-1 : x1[i](0.0) g(x) is same..... 3. fft(x1,len,1) ff

FFT NTT 错误总结(持续更新)

FFT NTT错误总结 1 处理\(r\)数组时忘记赋值 r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1)); 2 负数重载运算符 point operator * (point a,point b){ return point(a.x * b.x - a.y * b.y,a.x * b.y + a.y * b.x); } 3 欧拉公式记不清楚 point Wn = point(cos(Pi / mid),type *

FFT/NTT基础题总结

在学各种数各种反演之前把以前做的$FFT$/$NTT$的题整理一遍 还请数论$dalao$口下留情 T1快速傅立叶之二 题目中要求求出 $c_k=\sum\limits_{i=k}^{n-1}a_i*b_{i-k}$ 首先可以把$a$翻转, $c_k=\sum\limits_{i=k}^{n-1}a_{n-1-i}*b_{i-k}$ $c_k=\sum\limits_{i=0}^{n-k-1}a_{n-k-1-i}*b_{i}$ 也就是说对新的$a$,$b$数组做一遍$FFT$得到的便是$c$数

多项式$fft$,$ntt$,$fwt$初步

最近在学多项式和生成函数. 上课听$lnc$大神讲还是$mengbier$. 作为多项式的前置芝士,$fft,ntt$等是必学的. 在此记录一些关于$fft,ntt,fwt$的知识及例题... FFT: 应用在处理$\sum _{i+j=k} f[i]*g[j]$的卷积上. 看网上大佬的博客,基本入了门吧. 自己的关于原理的一些见解: 多项式有系数表示和点值表示,两种表示方法可以相互转化. FFT可以在$O(n*longn)$内解决多项式乘法. 具体是,点值表示的方法应用在多项式上是$O(n)$

HDU-4609(FFT/NTT)

HDU-4609(FFT/NTT) 题意: 给出n个木棒,现从中不重复地选出3根来,求能拼出三角形的概率. 计算合法概率容易出现重复,所以建议计算不合法方案数 枚举选出的最大边是哪条,然后考虑剩下两条边之和小于等于它 两条边之和为\(x\)的方案数可以\(FFT/NTT\)得到,是一个简单的构造 即\(f(x)=\sum x^{length_i}\),求出\(f(x)^2\),就能得到和的方案数,但是会重复,包括自己和自己算,一对算两次 处理一下前缀和即可 #include<bits/stdc+

HDU-5730(CDQ+FFT/NTT)

HDU-5730(CDQ+FFT/NTT) 题意:将长度为\(n\)的序列分成若干段,每段\([l,r]\)的权值为\(a_{r-l+1}\),一种分法的权值为所有段的乘积,求所有可能的分法的权值和 根据题意可以得到简单\(dp\) \(dp_0=1,dp_i=\sum_0^{i-1}dp_j \cdot a_{i-j}\) 可以看到是一个\(i-j\)形式的作差卷积 但是直接卷积我们无法保证先求出了\(dp_j\),所有可以用\(CDQ\)分治优化,复杂度\(n\log^2 n\) 具体实现见