标签:模板 www. 多项式运算 return amp for 数组 code htm
现在的码风又变了。。。
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));
}
标签:模板 www. 多项式运算 return amp for 数组 code htm
原文地址:https://www.cnblogs.com/flashhu/p/10146087.html