多项式笔记
多项式,清空,封装,边界,是讨厌的。
目录
其实我不会做目录。
现已加入(按加入时间排序):
- NTT
- 多项式求逆
- 多项式对数函数
- 多项式指数函数
- 泰勒展开,牛顿迭代
- 多项式除法
- 多项式快速幂
- 多项式开根
然后还有的东西会慢慢加(好困)
预知识
背下来
泰勒展开
我不会不敢乱讲
大概的意思是用多项式来拟合一些不好求的函数。应用就是下面的牛顿迭代。
牛顿迭代
已知
求解
结论:
证明:
首先使用泰勒展开,将 在 处展开
得到
由于
所以在 的情况下,
所以原式展开:
化简一下即可得到
导数相关小知识
( 为常数)
NTT
懒得讲原理,喵。
ll A[maxn],B[maxn],pos[maxn],S[maxn];
const int mod=998244353,g=3,ginv=332748118;
ll ksm(ll x,int y)
{
ll ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod; y>>=1;
}
return ret;
}
int pre(int n,int m)
{
int lim=0;
while((1<<lim)<=n+m) lim++;
for(int i=0;i<=(1<<lim);i++)
pos[i]=(pos[i>>1]>>1)|((i&1)<<(lim-1));
return lim;
}
void NTT(ll *f,ll n,int opt)
{
for(int i=0;i<n;i++) if(i<pos[i]) swap(f[i],f[pos[i]]);
for(int i=1;i<n;i<<=1)
{
ll step=ksm((opt>0?g:ginv),(mod-1)/(2*i));
for(int j=0;j<n;j+=i+i)
{
ll cur=1;
for(int k=j;k<j+i;k++)
{
int gx=f[k],hx=1ll*cur*f[k+i]%mod;
f[k]=(gx+hx)%mod;f[k+i]=(gx-hx+mod)%mod;
cur=cur*step%mod;
}
}
}
if(opt==-1)
{
int ninv=ksm(n,mod-2);
for(int i=0;i<n;i++) f[i]=f[i]*ninv%mod;
}
}
void MUL(ll *s,ll *f,ll *h,int n,int m)
{
int lim=pre(n,m);
for(int i=0;i<=n;i++) A[i]=f[i];
for(int i=0;i<=m;i++) B[i]=h[i];
for(int i=n+1;i<=(1<<lim);i++) A[i]=0;
for(int i=m+1;i<=(1<<lim);i++) B[i]=0;
NTT(A,(1<<lim),1);NTT(B,(1<<lim),1);
for(int i=0;i<=(1<<lim)-1;i++) s[i]=A[i]*B[i]%mod;
NTT(s,(1<<lim),-1);
}
多项式求逆
给出,求出 使得
令
两边同时乘个
然后已知 就能做了。递归下去就行了。。
一般都写成非递归。
void INV(ll *s,ll *f,int n)
{
S[0]=ksm(f[0],mod-2);S[1]=0;
for(int len=2;len<=(n<<1);len<<=1)
{
ll lim=(len<<1);
for(int i=0;i<len;i++) A[i]=f[i],B[i]=S[i];
for(int i=len;i<lim;i++) A[i]=B[i]=0;
pre(len,0);
NTT(A,lim,1); NTT(B,lim,1);
for(int j=0;j<lim;j++)
S[j]=(2*B[j]%mod+mod-A[j]*B[j]%mod*B[j]%mod)%mod;
NTT(S,lim,-1);
for(int j=len;j<lim;j++) S[j]=0;
}
for(int i=0;i<=n;i++) s[i]=S[i];
}
多项式对数函数(ln)
设
同时求导
然后复合函数求导拆开
然后先求导,再求逆,最后积分一下就行。
求导:
积分:
多项式指数函数(exp)
给出 求
令 ,那么
令
然后就能算了。
多项式除法
给 项多项式 , 和 项多项式 ,求 项的多项式 ,以及 项的 ,满足
神奇的转化。
令 为把 翻转过来后的多项式,一定有 。
把 代入上式,
式子同时乘 ,得到
然后
直接多项式求逆即可
多项式开根
已知 ,求
令
牛顿迭代,令
然后稍微化简一下,
多项式快速幂
已知 和 ,求
同时取 ,
前提是
全套模板(未完工)
namespace POLY
{
ll A[maxn],B[maxn],pos[maxn],S[maxn];
const int mod=998244353,g=3,ginv=332748118;
ll ksm(ll x,int y)
{
ll ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod; y>>=1;
}
return ret;
}
int pre(int n,int m)
{
int lim=0;
while((1<<lim)<=n+m) lim++;
for(int i=0;i<=(1<<lim);i++)
pos[i]=(pos[i>>1]>>1)|((i&1)<<(lim-1));
return lim;
}
void NTT(ll *f,ll n,int opt)
{
for(int i=0;i<n;i++) if(i<pos[i]) swap(f[i],f[pos[i]]);
for(int i=1;i<n;i<<=1)
{
ll step=ksm((opt>0?g:ginv),(mod-1)/(2*i));
for(int j=0;j<n;j+=i+i)
{
ll cur=1;
for(int k=j;k<j+i;k++)
{
int gx=f[k],hx=1ll*cur*f[k+i]%mod;
f[k]=(gx+hx)%mod;f[k+i]=(gx-hx+mod)%mod;
cur=cur*step%mod;
}
}
}
if(opt==-1)
{
int ninv=ksm(n,mod-2);
for(int i=0;i<n;i++) f[i]=f[i]*ninv%mod;
}
}
void MUL(ll *s,ll *f,ll *h,int n,int m)
{
int lim=pre(n,m);
for(int i=0;i<=n;i++) A[i]=f[i];
for(int i=0;i<=m;i++) B[i]=h[i];
for(int i=n+1;i<=(1<<lim);i++) A[i]=0;
for(int i=m+1;i<=(1<<lim);i++) B[i]=0;
NTT(A,(1<<lim),1);NTT(B,(1<<lim),1);
for(int i=0;i<=(1<<lim)-1;i++) s[i]=A[i]*B[i]%mod;
NTT(s,(1<<lim),-1);
}
void INV(ll *s,ll *f,int n)
{
S[0]=ksm(f[0],mod-2);S[1]=0;
for(int len=2;len<=(n<<1);len<<=1)
{
ll lim=(len<<1);
for(int i=0;i<len;i++) A[i]=f[i],B[i]=S[i];
for(int i=len;i<lim;i++) A[i]=B[i]=0;
pre(len,0);
NTT(A,lim,1); NTT(B,lim,1);
for(int j=0;j<lim;j++)
S[j]=(2*B[j]%mod+mod-A[j]*B[j]%mod*B[j]%mod)%mod;
NTT(S,lim,-1);
for(int j=len;j<lim;j++) S[j]=0;
}
for(int i=0;i<=n;i++) s[i]=S[i];
}
void ADD(ll *s,ll *f,ll *h,int n,int m)
{
for(int i=0;i<=max(n,m);i++) s[i]=(f[i]+h[i])%mod;
}
void DEL(ll *s,ll *f,ll *h,int n,int m)
{
for(int i=0;i<=max(n,m);i++) s[i]=(f[i]-h[i]+mod)%mod;
}
void REV(ll *f,int n)
{
for(int i=0;i<=n/2;i++) swap(f[i],f[n-i]);
}
void DIV(ll *q,ll *r,ll *f,ll *h,int n,int m)
{
static ll A[maxn],B[maxn],C[maxn],D[maxn];
for(int i=0;i<=n;i++) A[i]=C[i]=f[i];
for(int i=0;i<=m;i++) B[i]=D[i]=h[i];
REV(A,n);
REV(B,m);
INV(B,B,n-m);
MUL(q,A,B,n,n-m);
for(int i=n-m+1;i<=n+n-m;i++) q[i]=0;
REV(q,n-m);
MUL(D,D,q,m,n-m);
DEL(r,C,D,n,n);
}
void SQRT(ll *s,ll *f,int n)
{
static ll S[maxn],A[maxn],B[maxn],C[maxn];
S[0]=1;
for(int len=1;len<=(n<<1ll);len<<=1)
{
ll lim=len<<1;
for(int i=0;i<len;i++) A[i]=f[i],B[i]=S[i];
for(int i=len;i<lim;i++) A[i]=B[i]=C[i]=0;
INV(C,B,len);
pre(len,0); NTT(A,lim,1); NTT(C,lim,1);
for(int j=0;j<lim;j++) S[j]=A[j]*C[j]%mod;
NTT(S,lim,-1);
ADD(S,S,B,lim,lim);
ll inv2=ksm(2,mod-2);
for(int i=0;i<lim;i++) S[i]=S[i]*inv2%mod;
for(int i=len;i<lim;i++) S[i]=0;
}
for(int i=0;i<=n;i++) s[i]=S[i];
}
void MUL_integer(ll *s,ll *f,int n,ll k)
{
for(int i=0;i<=n;i++) S[i]=f[i]*k%mod;
for(int i=0;i<=n;i++) s[i]=S[i];
}
void DERIV(ll *s,ll *f,int n)
{
static ll A[maxn];A[n]=0;
for(int i=1;i<=n;i++) A[i-1]=f[i]*i%mod;
for(int i=0;i<=n;i++) s[i]=A[i];
}
void LIMIT(ll *s,ll *f,int n)
{
A[0]=0;
for(int i=0;i<n;i++) A[i+1]=f[i]*ksm(i+1,mod-2)%mod;
for(int i=0;i<=n;i++) s[i]=A[i];
}
void Ln(ll *s,ll *f,int n)
{
static ll A[maxn],B[maxn];
int lim=pre(n,n);
for(int i=0;i<=n;i++) A[i]=f[i],B[i]=0;
for(int i=n+1;i<=(1<<lim);i++) A[i]=B[i]=0;
DERIV(B,A,n);
INV(A,A,n);
MUL(A,A,B,n,n);
LIMIT(A,A,n);
for(int i=0;i<=n;i++) s[i]=A[i];
}
void EXP(ll *s,ll *f,int n)
{
static ll A[maxn],B[maxn],C[maxn],S[maxn];
S[0]=1; S[1]=0;
for(ll len=2;len<=(n<<1);len<<=1)
{
int lim=len<<1;
for(int i=0;i<len;i++) A[i]=f[i],B[i]=S[i];
for(int i=len;i<lim;i++) A[i]=B[i]=C[i]=0;
Ln(C,B,len-1);
for(int i=0;i<len;i++) C[i]=(A[i]-C[i]+mod)%mod;
C[0]=(C[0]+1)%mod;
pre(len,0); NTT(B,lim,1); NTT(C,lim,1);
for(int j=0;j<lim;j++) S[j]=B[j]*C[j]%mod;
NTT(S,lim,-1);
for(int j=len;j<lim;j++ )S[j]=0;
}
for(int i=0;i<=n;i++) s[i]=S[i];
}
void POW(ll *s,ll *f,int n,ll k)
{
int lim=pre(n,n);
for(int i=0;i<=n;i++) A[i]=f[i];
for(int i=n+1;i<=(1<<lim);i++) A[i]=0;
Ln(A,A,n); MUL_integer(A,A,n,k);
EXP(A,A,n);
for(int i=0;i<=n;i++) s[i]=A[i];
}
const int img=86583718;
void sin(ll *s,ll *f,int n)
{
static ll S[maxn],H[maxn];
for(int i=0;i<=n;i++) S[i]=f[i]*img%mod;
EXP(S,S,n); INV(H,S,n);
ll t=ksm(2*img%mod,mod-2);
for(int i=0;i<=n;i++)
s[i]=(S[i]-H[i]+mod)%mod*t%mod;
}
void cos(ll *s,ll *f,int n)
{
static ll S[maxn],H[maxn];
for(int i=0;i<=n;i++) S[i]=f[i]*img%mod;
EXP(S,S,n); INV(H,S,n);
ll t=ksm(2,mod-2);
for(int i=0;i<=n;i++)
s[i]=(S[i]+H[i])%mod*t%mod;
}
void ARCSIN(ll *s,ll *f,int n)
{
static ll A[maxn],B[maxn];
for(int i=0;i<=n;i++) A[i]=B[i]=f[i];
DERIV(B,B,n); MUL(A,A,A,n,n);
for(int i=0;i<=n;i++) A[i]=(mod-A[i])%mod;
A[0]=(A[0]+1)%mod;
SQRT(A,A,n);
INV(A,A,n);
MUL(A,A,B,n,n);
LIMIT(A,A,n);
for(int i=0;i<=n;i++) s[i]=A[i];
}
void ARCTAN(ll *s,ll *f,int n)
{
static ll A[maxn],B[maxn];
for(int i=0;i<=n;i++) A[i]=B[i]=f[i];
DERIV(B,B,n); MUL(A,A,A,n,n);
A[0]=(A[0]+1)%mod;
INV(A,A,n);
MUL(A,A,B,n,n);
LIMIT(A,A,n);
for(int i=0;i<=n;i++) s[i]=A[i];
}
}
留个坑(((
本文作者:cc0000
本文链接:https://www.cnblogs.com/cc0000/p/17009204.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步