多项式板子

缺开方,多点求值。

#include<bits/stdc++.h> #define int long long using namespace std; const int p=998244353,G=3; const int N=1e6+5; int rev[N]; int qpow(int a,int b) { int ans=1; while(b) { if(b&1) ans=ans*a%p; a=a*a%p; b>>=1; } return ans; } void change(vector<int> &x,int len) { for(int i=0; i<len; i++) { rev[i]=rev[i>>1]>>1; if(i&1) rev[i]|=(len>>1); } for(int i=0; i<len; i++) if(rev[i]>i) swap(x[i],x[rev[i]]); } void ntt(vector<int> &x,int len,int flag) { change(x,len); for(int i=1; i<len; i<<=1) { int gn=qpow(flag==1?G:qpow(G,p-2),(p-1)/(i<<1)); for(int j=0; j<len; j+=(i<<1)) { int g=1; for(int k=j; k<j+i; k++) { int l=x[k],r=g*x[k+i]%p; x[k]=(l+r)%p,x[k+i]=(l-r+p)%p; g=g*gn%p; } } } if(flag==-1) { int inv=qpow(len,p-2); for(int i=0; i<len; i++) x[i]=x[i]*inv%p; } } struct poly { mutable vector<int> x; void read(int n) {x.resize(n);for(int i=0; i<n; i++) cin>>x[i];} void write(int n=-1) {if(!~n) n=x.size();for(int i=0; i<n; i++) cout<<x[i]<<" ";cout<<"\n";} poly operator+(const poly &o) const { poly a=*this,b=o; int len=max(a.x.size(),b.x.size()); a.x.resize(len),b.x.resize(len); for(int i=0; i<len; i++) a.x[i]=(a.x[i]+b.x[i])%p; return a; } poly operator-(const poly &o) const { poly a=*this,b=o; int len=max(a.x.size(),b.x.size()); a.x.resize(len),b.x.resize(len); for(int i=0; i<len; i++) a.x[i]=(a.x[i]-b.x[i]+p)%p; return a; } poly operator*(const poly &o) const { poly a=*this,b=o; int len=1,tmp=a.x.size()+b.x.size()-1; while(len<tmp) len<<=1; a.x.resize(len),b.x.resize(len); ntt(a.x,len,1),ntt(b.x,len,1); for(int i=0; i<len; i++) a.x[i]=a.x[i]*b.x[i]%p; ntt(a.x,len,-1); a.x.resize(tmp); return a; } poly operator*(const int &o) const { poly a=*this; for(int i=0; i<a.x.size(); i++) a.x[i]=(a.x[i]*o%p+p)%p; return a; } poly inv() { poly a=*this,b,s,t; int n=a.x.size(); b.x.resize(n<<1); b.x[0]=qpow(a.x[0]%p,p-2); int len=2; while(len<2*a.x.size()) { s.x.resize(len),t.x.resize(len); for(int i=0; i<len; i++) s.x[i]=a.x[i]; for(int i=0; i<len; i++) t.x[i]=b.x[i]; for(int i=0; i<len; i++) b.x[i]=2*t.x[i]%p; s=s*t*t; for(int i=0; i<len; i++) b.x[i]=(b.x[i]-s.x[i]+p)%p; len<<=1; } b.x.resize(n); return b; } poly operator/(const poly &o) const { poly a=*this,b=o; int n=a.x.size(),m=b.x.size(); reverse(a.x.begin(),a.x.end()); reverse(b.x.begin(),b.x.end()); b.x.resize(n-m+2); a=a*b.inv(); a.x.resize(n-m+1); reverse(a.x.begin(),a.x.end()); return a; } poly operator%(const poly &o) const { poly a=*this,b=o; poly c=a-a/b*b; c.x.resize(b.x.size()-1); return c; } poly dao() { poly a=*this; for(int i=0; i<a.x.size()-1; i++) a.x[i]=a.x[i+1]*(i+1)%p; a.x.pop_back(); return a; } poly ji() { poly a=*this;a.x.push_back(0); for(int i=a.x.size()-1; i>=1; i--) a.x[i]=a.x[i-1]*qpow(i,p-2)%p; a.x[0]=0; return a; } poly ln() { poly a=*this; int n=a.x.size(); a=(a.dao()*a.inv()).ji(); a.x.resize(n); return a; } poly exp() { poly a=*this,b,s,t; int n=a.x.size(); b.x.resize(n<<1); b.x[0]=1; int len=2; while(len<(n<<1)) { s.x.resize(len),t.x.resize(len); for(int i=0; i<len; i++) s.x[i]=a.x[i]; for(int i=0; i<len; i++) t.x[i]=b.x[i]; s=t.ln()*(-1)+s; s.x[0]=(s.x[0]+1)%p; s=s*t; for(int i=0; i<len; i++) b.x[i]=s.x[i]; len<<=1; } b.x.resize(n); return b; } };

__EOF__

本文作者System_Error
本文链接https://www.cnblogs.com/System-Error/p/18698319.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   System_Error  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示