多项式exp & 牛顿迭代
牛顿迭代解决的是这样一个问题:已知
这个问题可以用倍增的方式解决。首先假设你知道了
然后,我们假设
将
考虑到
然后考虑这个东西怎么去实现多项式
首先我们看到模板题,假设给定的多项式是
Code Here
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5,mod=998244353,g=3,gi=332748118;
int n,rev[N<<2];
int qpow(int a,int b){
int ans=1,base=a;
while(b){
if(b&1)ans=ans*base%mod;
base=base*base%mod;
b>>=1;
}
return ans;
}
#define Poly vector<int>
Poly operator+(Poly x,Poly y){
Poly z;
z.resize(max(x.size(),y.size()));
x.resize(max(x.size(),y.size()));y.resize(max(x.size(),y.size()));
for(int i=0;i<z.size();++i)z[i]=(x[i]+y[i])%mod;
return z;
}
Poly operator-(Poly x,Poly y){
Poly z;
z.resize(max(x.size(),y.size()));
x.resize(max(x.size(),y.size()));y.resize(max(x.size(),y.size()));
for(int i=0;i<z.size();++i)z[i]=(x[i]-y[i]+mod)%mod;
return z;
}
void NTT(Poly &A,int n,int opt=1){
A.resize(n+1);
for(int i=0;i<n;++i)if(i<rev[i])swap(A[i],A[rev[i]]);
for(int mid=1;mid<n;mid<<=1){
int wn=qpow(opt==1?g:gi,(mod-1)/(mid<<1));
for(int i=0;i<n;i+=(mid<<1)){
int w=1;
for(int j=0;j<mid;++j,w=(w*wn)%mod){
int tmp0=A[i+j],tmp1=w*A[i+j+mid]%mod;
A[i+j]=(tmp0+tmp1)%mod;
A[i+j+mid]=(tmp0-tmp1)%mod;
}
}
}
}
Poly operator*(Poly x,Poly y){
rev[0]=0;
int lim=1,L=0;
while(lim<=x.size()+y.size()+3)lim<<=1ll,L++;
for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
x.resize(lim+1);y.resize(lim+1);
NTT(x,lim,1);NTT(y,lim,1);
for(int i=0;i<lim;++i)x[i]=x[i]*y[i]%mod;
NTT(x,lim,-1);
x.resize(lim+1);
int inv=qpow(lim,mod-2);
for(int i=0;i<lim;++i)x[i]=(x[i]*inv%mod+mod)%mod;
return x;
}
Poly _(Poly x,int w){
for(int i=0;i<x.size();++i)x[i]=(x[i]*w)%mod;
return x;
}
Poly Inv(Poly x,int n){
x.resize(n+1);
if(n==1){
// cout<<"Check: "<<x[0]<<' '<<qpow(x[0],mod-2)<<'\n';
Poly o;
o.push_back(qpow(x[0],mod-2));
return o;
}
Poly tmp=Inv(x,n>>1);
tmp.resize(n+1);
// cout<<"Check2: "<<n<<' '<<tmp.size()<<' '<<tmp[0]<<'\n';
tmp=_(tmp,2)-x*tmp*tmp;
tmp.resize(n+1);
return tmp;
}
Poly inv(Poly x){
int n=x.size();
int lim=1;
while(lim<=n)lim<<=1;
x.resize(lim+1);
Poly ans=Inv(x,lim);
ans.resize(lim+1);
return ans;
}
Poly Derive(Poly x){
Poly ans;
for(int i=1;i<x.size();++i)ans.push_back(i*x[i]%mod);
int n=x.size();
int lim=1;
while(lim<=n)lim<<=1;
ans.resize(lim+1);
return ans;
}
Poly Integral(Poly x){
Poly ans;
ans.push_back(0);
for(int i=0;i<x.size();++i)ans.push_back(x[i]*qpow(i+1,mod-2)%mod);
int n=x.size();
int lim=1;
while(lim<=n)lim<<=1;
ans.resize(lim+1);
return ans;
}
Poly ln(Poly x){
Poly ans=Integral(Derive(x)*inv(x));
return ans;
}
Poly E(Poly x,int n){
x.resize(n+1);
if(n==1){
Poly now;
now.push_back(1);
return now;
}
Poly tmp=E(x,n+1>>1);
tmp.resize(n+1);
Poly tmp2=x-ln(tmp);
tmp2[0]=(tmp2[0]+1)%mod;
tmp2.resize(n+1);
Poly ans=tmp*tmp2;
ans.resize(n+1);
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
Poly a;
int n,lim=1;
cin>>n;
while(lim<=n)lim<<=1;
a.resize(lim+1);
for(int i=0;i<n;++i)cin>>a[i];
a=E(a,n+1);
for(int i=0;i<n;++i)cout<<a[i]<<' ';
return 0;
}
这个东西基本上也是我目前的多项式全家桶
特别注意一下乘法要把两个多项式 resize
成接近的大小,然后 rev
尽可能开大一点,不然很容易 RE
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现