多项式细节梳理&模板(多项式)

基础

很久以前的多项式总结

现在的码风又变了。。。

FFT和NTT的板子

typedef complex<double> C;
const double PI=acos(-1);
void FFT(C*a,R op){
    for(R i=0;i<N;++i)
        if(i<r[i])swap(a[i],a[r[i]]);
    for(R i=1;i<N;i<<=1){
        C wn=C(cos(PI/i),sin(PI/i)*op),w=1,t;
        for(R j=0;j<N;j+=i<<1,w=1)
            for(R k=j;k<j+i;++k,w*=wn)
                t=a[k+i]*w,a[k+i]=a[k]-t,a[k]+=t;
    }
}
const int YL=998244353;
LL qpow(LL b,R k){
    LL a=1;
    for(;k;k>>=1,b=b*b%YL)
        if(k&1)a=a*b%YL;
    return a;
}
void NTT(R*a,R n,R op){
    for(R i=0;i<n;++i)
        if(i<r[i])swap(a[i],a[r[i]]);
    for(R i=1;i<n;i<<=1){
        LL wn=qpow(3,(YL-1)/(i<<1));
        if(op==-1)wn=qpow(wn,YL-2);
        for(R j=0;j<n;j+=i<<1)
            for(R k=j,w=1,x,y;k<j+i;++k,w=w*wn%YL)
                x=a[k],y=(LL)a[k+i]*w%YL,a[k]=Mod(x+y),a[k+i]=Mod(x-y+YL);
    }
    if(op==1)return;
    R in=qpow(n,YL-2);
    for(R i=0;i<n;++i)a[i]=(LL)a[i]*in%YL;
}

多项式运算

牛顿迭代

已知多项式函数\(F(x)\),用倍增法求解\(B\)使得\(F(B)\equiv0(\mod x^{2^k})\)。
\(B_1=B-\frac{F(B)}{F'(B)}\)
接下来的\(A\)为已知多项式,B为待求多项式。

求逆

\(F(B)=AB-1=0\)
\(B_1=B-\frac{AB-1}{A}=B-B(AB-1)=2B-AB^2\)

开方

\(F(B)=B^2-A=0\)
\(B_1=B-\frac{B^2-A}{2B}=\frac{B^2+A}{2B}\)

对数

没必要迭代。
\(B=\ln A\)
\(B=\int\frac{A'}{A}\)

指数

\(B=e^A\)
\(\ln B-A=0\)
\(B_1=B-\frac{\ln B-A}{\frac1B}=B(1+A-\ln B)\)

代码模板

写的时候保证了一定的稳定性(数组清空问题),因此牺牲了一丁点效率。
参数中,a为已知,b为待求,a1、b1为辅助数组。
传入前需自己确保b、a1、b1是否为空。
返回后保证a维持原状,b存好答案,a1、b1为空。
还有开方,除法,拉格朗日反演待填坑

const int YL=998244353;
int Inv[N],r[N];//在外面初始化逆元
inline int Mod(const int x){
    return x>=YL?x-YL:x;
}
LL qpow(LL b,R k){
    LL a=1;
    for(;k;k>>=1,b=b*b%YL)
        if(k&1)a=a*b%YL;
    return a;
}
int Init(R m){
    R n=1;while(n<m<<1)n<<=1;
    for(R i=0;i<n;++i)r[i]=(r[i>>1]|(1&i)*n)>>1;
    return n;
}
void NTT(R*a,R n,R op){
    for(R i=0;i<n;++i)
        if(i<r[i])swap(a[i],a[r[i]]);
    for(R i=1;i<n;i<<=1){
        LL wn=qpow(3,(YL-1)/(i<<1));
        if(op==-1)wn=qpow(wn,YL-2);
        for(R j=0;j<n;j+=i<<1)
            for(R k=j,w=1,x,y;k<j+i;++k,w=w*wn%YL)
                x=a[k],y=(LL)a[k+i]*w%YL,a[k]=Mod(x+y),a[k+i]=Mod(x-y+YL);
    }
    if(op==1)return;
    R in=qpow(n,YL-2);
    for(R i=0;i<n;++i)a[i]=(LL)a[i]*in%YL;
}
void PolyDer(R*a,R*b,R n){
    for(R i=1;i<n;++i)b[i-1]=(LL)a[i]*i%YL;
    if(a==b)a[n-1]=0;
}
void PolyInt(R*a,R*b,R n){
    for(R i=n;i;--i)b[i]=(LL)a[i-1]*Inv[i]%YL;
    if(a==b)a[0]=0;
}
void PolyInv(R*a,R*b,R*a1,R m){
    if(m==1){b[0]=qpow(a[0],YL-2);return;}
    PolyInv(a,b,a1,(m+1)>>1);memcpy(a1,a,4*m);
    R n=Init(m);NTT(b,n,1);NTT(a1,n,1);
    for(R i=0;i<n;++i)b[i]=(YL+2-(LL)b[i]*a1[i]%YL)*b[i]%YL;
    NTT(b,n,-1);memset(a1,0,4*n);memset(b+m,0,4*(n-m));
}
void PolyLn(R*a,R*b,R*a1,R m){
    PolyInv(a,b,a1,m);PolyDer(a,a1,m);
    R n=Init(m);NTT(b,n,1);NTT(a1,n,1);
    for(R i=0;i<n;++i)b[i]=(LL)b[i]*a1[i]%YL;
    NTT(b,n,-1);memset(a1,0,4*n);PolyInt(b,b,m);
}
void PolyExp(R*a,R*b,R*a1,R*b1,R m){
    if(m==1){b[0]=1;return;}
    PolyExp(a,b,a1,b1,(m+1)>>1);PolyLn(b,b1,a1,m);memcpy(a1,a,4*m);
    R n=Init(m);NTT(b,n,1);NTT(a1,n,1);NTT(b1,n,1);
    for(R i=0;i<n;++i)b[i]=(LL)b[i]*(YL+1+a1[i]-b1[i])%YL;
    NTT(b,n,-1);memset(a1,0,4*n);memset(b1,0,4*n);memset(b+m,0,4*(n-m));
}

原文地址:https://www.cnblogs.com/flashhu/p/10146087.html

时间: 2024-07-31 12:41:06

多项式细节梳理&模板(多项式)的相关文章

[模板] 多项式全家桶

注意:以下所有说明均以帮助理解模板为目的,不保证正确性. 多项式求逆 已知$A(x)$,求满足$A(x)B(x)=1\ (mod\ x^n)$的B(以下为了方便假设n是2的幂) 考虑倍增,假设已经求出$A(x)B_0(x)=1\ (mod\ x^{n/2})$ $$A(x)(B(x)-B_0(x))=0\ (mod\ x^{n/2})$$ $$(B(x)-B_0(x))=0\ (mod\ x^{n/2})$$ $$(B(x)-B_0(x))^2=0\ (mod\ x^n)$$ $$B^2(x)-

多项式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

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

多项式相关算法模板

多项式乘法 1 #include <bits/stdc++.h> 2 using namespace std; 3 const double pi = acos(-1); 4 const int LEN = 1e5 + 5; 5 int n, m, N; 6 namespace ploy { 7 struct comp { 8 double x, y; 9 } a[LEN * 4], b[LEN * 4]; 10 comp operator + (const comp &x,const

luogu P4238 多项式求逆 (模板题、FFT)

手动博客搬家: 本文发表于20181125 13:21:46, 原地址https://blog.csdn.net/suncongbo/article/details/84485718 题目链接: https://www.luogu.org/problemnew/show/P4238 题意: 给定\(n\)次多项式\(A(x)\), 求\(n\)次多项式\(B(x)\)满足\(B(x)A(x)\equiv 1(\mod x^n)\) 题解: DFT,每个数对\(998244353\)求逆元.IDF

[模板] 多项式: 乘法/求逆/分治fft/微积分/ln/exp/幂

多项式 代码 const int nsz=(int)4e5+50; const ll nmod=998244353,g=3,ginv=332748118ll; //basic math ll qp(ll a,ll b){ ll res=1; for(;b;a=a*a%nmod,b>>=1)if(b&1)res=res*a%nmod; return res; } ll inv(ll n){ return qp(n,nmod-2); } //polynomial operations //

多项式FFT相关模板

自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <algorithm> #include <vector> using namespace std; #de

Luogu5245 【模板】多项式快速幂(多项式exp)

A(x)k=eklnA(x),丝毫不懂为什么指数要对p取模,只是写下exp板子. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 600010 #define P 9

多项式函数插值:多项式形式函数求值的Horner嵌套算法

设代数式序列 $q_1(t), q_2(t), ..., q_{n-1}(t)$ ,由它们生成的多项式形式的表达式(不一定是多项式): $$p(t)=x_1+x_2q_1(t)+...x_nq_1(t)q_2(t)..q_{n-1}(t)=\sum\limits_{i=1}^n(x_i\prod\limits_{j=1}^{i-1}q_j(t))$$ 一般来讲,按照这个形式计算函数在 $t_0$ 点的取值的复杂度为:n-1次 $q_i(t)$ 求值,n-1次浮点数乘法(生成n个不同的乘积),n-