NTT:
namespace NTT {
int n,m,l,r[N];
void NTT(int *a,int f) {
for(int i=0;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<n;i<<=1) {
int wn=q_pow(pr,phi/(i<<1));
if(f==-1) wn=q_pow(wn,mod-2);
for(int p=i<<1,j=0;j<n;j+=p) {
int w=1;
for(int k=0;k<i;k++,w=1ll*w*wn%mod) {
int x=a[j+k],y=1ll*w*a[j+k+i]%mod;
a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
}
}
}
if(f==-1) {
int inv=q_pow(n,mod-2);
for(int i=0;i<=n;i++) a[i]=1ll*a[i]*inv%mod;
}
}
int calc(int *a,int *b,int _n,int _m,int type) {//type==2是多项式求逆时用的
n=_n,m=_m,l=0;
m+=n;for(n=1;n<=m;n<<=1) l++;
for(int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
NTT(a,1);NTT(b,1);
for(int i=0;i<=n;i++) {
if(type==1) a[i]=1ll*a[i]*b[i]%mod;
else a[i]=1ll*a[i]*b[i]%mod*b[i]%mod;
}
NTT(a,-1);return n;
}
}
分治NTT:
void cdq(int l,int r) {
if(l==r) {
f[l]=((1ll*q_pow(2,1ll*l*(l-1)/2)*q_pow(fac[l-1],mod-2)%mod-f[l])%mod+mod)%mod;//具体视题目推出的式子而定,这里是bzoj3456城市规划的代码
return;
}
int mid=(l+r)>>1;
cdq(l,mid);
for(int i=0;i<=mid-l;i++) a[i]=f[i+l];
for(int i=0;i<=r-l;i++) b[i]=g[i];
int tmp=NTT::calc(a,b,mid-l,r-l);
for(int i=mid+1-l;i<=r-l;i++) f[i+l]=(f[i+l]+a[i])%mod;
for(int i=0;i<=tmp;i++) a[i]=b[i]=0;
cdq(mid+1,r);
}
多项式求逆:
void Inv(int *f,int *g,int len) {
if(len==1) {
g[0]=q_pow(f[0],mod-2);
return;
}
Inv(f,g,len>>1);
for(int i=0;i<len;i++) a[i]=f[i],b[i]=g[i];
int tmp=NTT::calc(a,b,len-1,len-1,2);
for(int i=0;i<len;i++) g[i]=((-a[i]+2*g[i])%mod+mod)%mod;
for(int i=0;i<=tmp;i++) a[i]=b[i]=0;
}
多项式开根:
不会,留坑
原文地址:https://www.cnblogs.com/gczdajuruo/p/8455771.html
时间: 2024-10-09 00:02:14