多项式十九连

xenonex

2018-11-28 13:13:39

Personal

P3803 [【模板】多项式乘法(FFT)](https://www.luogu.org/problemnew/show/P3803) P1919 [【模板】A*B Problem升级版(FFT快速傅里叶)](https://www.luogu.org/problemnew/show/P1919) P4245 [【模板】任意模数NTT](https://www.luogu.org/problemnew/show/P4245) P4238 [【模板】多项式求逆](https://www.luogu.org/problemnew/show/P4238) P4239 [【模板】多项式求逆(加强版)](https://www.luogu.org/problemnew/show/P4239) P4721 [【模板】分治 FFT](https://www.luogu.org/problemnew/show/P4721) P4512 [【模板】多项式除法](https://www.luogu.org/problemnew/show/P4512) P4723 [【模板】线性递推](https://www.luogu.org/problemnew/show/P4723) P4725 [【模板】多项式对数函数](https://www.luogu.org/problemnew/show/P4725) P4726 [【模板】多项式指数函数](https://www.luogu.org/problemnew/show/P4726) P5205 [【模板】多项式开根](https://www.luogu.org/problemnew/show/P5205) P5277 [【模板】多项式开根(加强版)](https://www.luogu.org/problemnew/show/P5277) P5245 [【模板】多项式快速幂](https://www.luogu.org/problemnew/show/P5245) P5273 [【模板】多项式幂函数(加强版)](https://www.luogu.org/problemnew/show/P5273) P5264 [【模板】多项式三角函数](https://www.luogu.org/problemnew/show/P5264) P5265 [【模板】多项式反三角函数](https://www.luogu.org/problemnew/show/P5265) P5050 [【模板】多项式多点求值](https://www.luogu.org/problemnew/show/P5050) P5158 [【模板】多项式快速插值](https://www.luogu.org/problemnew/show/P5158) P5282 [【模板】快速阶乘算法](https://www.luogu.org/problemnew/show/P5282) 奇怪的板子 ```cpp #include<cstdio> #include<cstring> #define L 262144 #define mod 998244353 typedef long long LL; typedef unsigned long long ULL; int rev[L<<1],W[L],_i[19],inv[L]; int pool[5242880],*ptr,*src,*dst,*pi[L],cpitmp[L],*mou[18],intmp[L]; inline int invx(int x){int r=1;for(x%=mod;x>1;x=mod%x)r=LL(mod-mod/x)*r%mod;return r;} inline int ksm(LL a,LL b){int r=1;for(;b;a=a*a%mod,b>>=1)if(b&1)r=r*a%mod;return r;} void NTT_Init() { int i,j,t; const int G = 3,i2 = invx(2),l = L>>1; for(i=j=1;j<L;j<<=1)for(;i<j<<1;i++)rev[i<<1]=rev[i],rev[i<<1|1]=rev[i]|j; t = ksm(G,mod/L), W[l] = 1; for(i=1;i<l;i++)W[i+l] = (LL)W[i+l-1]*t%mod; for(i=l-1;i;i--)W[i] = W[i<<1]; for(_i[0]=i=1;i<19;i++)_i[i] = (LL)_i[i-1]*i2%mod; for(inv[1]=1,i=2;i<L;i++)inv[i] = LL(mod-mod/i)*inv[mod%i]%mod; } void NTT(int *a,int len,int sign) { static ULL f[L]; int h,i,j,k,*w,t; ULL *p,*q; for(w=rev+len,i=0;i<len;i++)f[*w++] = a[i]; for(h=0,i=1;i<len;h++,i<<=1) { if(h == 16)for(j=0;j<len;j++)f[j] %= mod; for(j=0;j<len;j+=i,j+=i)for(w=W+i,q=(p=f+j)+i,k=0;k<i;k++,p++,q++) t = *q**w++%mod, *q = *p+mod-t, *p += t; } if(sign < 0)for(a[0]=f[0]*(k=_i[h])%mod,i=1;i<len;i++)a[len-i]=f[i]*k%mod; else for(i=0;i<len;i++)a[i] = f[i]%mod; } void poly_inv(int *a,int len,int *f) { static int invtmp[L]; int l,l2,i;len <<= 1; memset(f,0,len<<2), memset(invtmp,0,len<<2); for(f[0]=invx(a[0]),l=2,l2=4;l<len;l<<=1,l2<<=1) { memcpy(invtmp,a,l<<2), NTT(invtmp,l2,1), NTT(f,l2,1); for(i=0;i<l2;i++)f[i] = f[i]*(2-(LL)invtmp[i]*f[i]%mod+mod)%mod; NTT(f,l2,-1), memset(f+l,0,l<<2); } } void poly_div(int *a,int lena,int *b,int lenb,int *f,int *g) { static int divtmp1[L],divtmp2[L]; int lenf = lena-lenb+1,l,i,j; if(lena < lenb){memcpy(g,a,lena<<2);memset(g+lena,0,(lenb-lena-1)<<2);return;} for(l=1;l<lenf;l<<=1);l <<= 1; for(i=0;i<lenb;i++)divtmp1[lenb-i-1] = b[i]; j = lenb; if(j > lenf){j = lenf;}memset(divtmp1+j,0,(l-j)<<2); for(poly_inv(divtmp1,l>>1,f),NTT(f,l,1),i=0;i<lena;i++)divtmp1[lena-i-1] = a[i]; j = lena; if(j > lenf){j = lenf;}memset(divtmp1+j,0,(l-j)<<2), NTT(divtmp1,l,1); for(i=0;i<l;i++)f[i] = (LL)f[i]*divtmp1[i]%mod; for(NTT(f,l,-1),i=0,j=lenf-1;i<j;i++,j--)l = f[i], f[i] = f[j], f[j] = l; for(l=1;l<lena;l<<=1); memcpy(divtmp1,f,lenf<<2), memset(divtmp1+lenf,0,(l-lenf)<<2), NTT(divtmp1,l,1); memcpy(divtmp2,b,lenb<<2), memset(divtmp2+lenb,0,(l-lenb)<<2), NTT(divtmp2,l,1); for(i=0;i<l;i++)divtmp1[i] = (LL)divtmp1[i]*divtmp2[i]%mod; for(NTT(divtmp1,l,-1),i=0;i<lena;i++)if((g[i]=a[i]-divtmp1[i]) < 0)g[i] += mod; } void poly_sqrt(int *a,int len,int *f) { static int sqrtmp[L],sqrtmp2[L]; int l,l2,i;len <<= 1; memset(f,0,len<<2), memset(sqrtmp2,0,len<<2); for(f[0]=1,l=2,l2=4;l<len;l<<=1,l2<<=1) { poly_inv(f,l,sqrtmp), memcpy(sqrtmp2,a,l<<2); NTT(sqrtmp,l2,1), NTT(sqrtmp2,l2,1); for(i=0;i<l2;i++)sqrtmp[i] = (LL)sqrtmp[i]*sqrtmp2[i]%mod; NTT(sqrtmp,l2,-1); for(i=l>>1;i<l;i++)f[i] = sqrtmp[i]&1?(sqrtmp[i]+mod)>>1:sqrtmp[i]>>1; } } void poly_ln(int *a,int len,int *f) { static int lntmp[L]; int i,l = len<<1; for(poly_inv(a,len,lntmp),i=0;i<len;i++)f[i] = a[i+1]*LL(i+1)%mod; memset(f+len-1,0,(len+1)<<2); for(NTT(lntmp,l,1),NTT(f,l,1),i=0;i<l;i++)lntmp[i] = (LL)lntmp[i]*f[i]%mod; NTT(lntmp,l,-1), memset(f+len,0,len<<2); for(f[0]=0,i=1;i<len;i++)f[i] = (LL)inv[i]*lntmp[i-1]%mod; } void poly_exp(int *a,int len,int *f) { static int exptmp[L],exptmp2[L]; int l,l2,i;len <<= 1; memset(f,0,len<<2), memset(exptmp2,0,len<<2); for(f[0]=1,l=2,l2=4;l<len;l<<=1,l2<<=1) { memcpy(exptmp2,a,l<<2); poly_ln(f,l,exptmp), NTT(f,l2,1), NTT(exptmp,l2,1), NTT(exptmp2,l2,1); for(i=0;i<l2;i++)f[i] = f[i]*LL(1-exptmp[i]+mod+exptmp2[i])%mod; NTT(f,l2,-1), memset(f+l,0,l<<2); } } void poly_sincos(int *a,int len,int *fsin,int *fcos) { static int sctmp1[L],sctmp2[L],sctmp3[L]; int I,i; for(I=W[3],i=0;i<len;i++)sctmp1[i] = (LL)a[i]*I%mod; poly_exp(sctmp1,len,sctmp2), poly_inv(sctmp2,len,sctmp3); if(fsin){for(I=invx(W[3]<<1),i=0;i<len;i++) {fsin[i] = LL(sctmp2[i]-sctmp3[i]+mod)*I%mod;}memset(fsin+len,0,len<<2);} if(fcos){for(I=invx(W[2]<<1),i=0;i<len;i++) {fcos[i] = LL(sctmp2[i]+sctmp3[i])*I%mod;}memset(fcos+len,0,len<<2);} } void poly_asin(int *a,int len,int *f) { static int asintmp[L]; int l = len<<1,i; memcpy(asintmp,a,len<<2), memset(asintmp+len,0,len<<2); for(NTT(asintmp,l,1),i=0;i<l;i++)asintmp[i] = (LL)asintmp[i]*asintmp[i]%mod; for(NTT(asintmp,l,-1),asintmp[0]=1,i=2;i<len;i++)asintmp[i] = mod-asintmp[i]; poly_sqrt(asintmp,len,f), poly_inv(f,len,asintmp); for(i=1;i<len;i++)f[i-1] = (LL)a[i]*i%mod; f[len-1] = 0, NTT(f,l,1), NTT(asintmp,l,1); for(i=0;i<l;i++)asintmp[i] = (LL)f[i]*asintmp[i]%mod; for(NTT(asintmp,l,-1),f[0]=0,i=1;i<len;i++)f[i] = (LL)asintmp[i-1]*inv[i]%mod; memset(f+len,0,len<<2); } void poly_atan(int *a,int len,int *f) { static int atantmp[L]; int l = len<<1,i; memcpy(atantmp,a,len<<2), memset(atantmp+len,0,len<<2); for(NTT(atantmp,l,1),i=0;i<l;i++)atantmp[i] = (LL)atantmp[i]*atantmp[i]%mod; NTT(atantmp,l,-1), atantmp[0] = 1; poly_inv(atantmp,len,f), memcpy(atantmp,f,l<<2); for(i=1;i<len;i++)f[i-1] = (LL)a[i]*i%mod; f[len-1] = 0, NTT(f,l,1), NTT(atantmp,l,1); for(i=0;i<l;i++)atantmp[i] = (LL)f[i]*atantmp[i]%mod; for(NTT(atantmp,l,-1),f[0]=0,i=1;i<len;i++)f[i] = (LL)atantmp[i-1]*inv[i]%mod; memset(f+len,0,len<<2); } void _calc_pi(int t,int l,int r,int siz) { pi[t] = ptr, ptr += siz; if(l == r){pi[t][0] = mod-src[l], pi[t][1] = 1;return;} int mid = (l+r)>>1,i,*p = pi[t],*q = cpitmp; _calc_pi(t<<1,l,mid,siz>>1), _calc_pi(t<<1|1,mid+1,r,siz>>1); memcpy(cpitmp,pi[t<<1],siz<<1), memset(cpitmp+(siz>>1),0,siz<<1), NTT(cpitmp,siz,1); memcpy(pi[t],pi[t<<1|1],siz<<1), NTT(pi[t],siz,1); for(i=0;i<siz;i++,p++,q++)*p = (LL)*p**q%mod; NTT(pi[t],siz,-1); } void _calc_eval(int *f,int len,int t,int l,int r,int dep) { poly_div(f,len,pi[t],r-l+2,cpitmp,mou[dep]); if(l == r){dst[l] = *mou[dep];return;} int mid = (l+r)>>1; _calc_eval(mou[dep],r-l+1,t<<1,l,mid,dep-1); _calc_eval(mou[dep],r-l+1,t<<1|1,mid+1,r,dep-1); } void poly_eval(int *func,int len,int *pts,int cnt,int *res) { int lc,logc,i; for(lc=1,logc=0;lc<cnt;lc<<=1,logc++); memset(pool,0,(lc<<3)*(logc+1)); ptr = pool, src = pts, dst = res; _calc_pi(1,0,cnt-1,lc<<1); for(i=0;i<=logc;i++)mou[i] = ptr, ptr += 2<<i; _calc_eval(func,len,1,0,cnt-1,logc); } void _calc_inte(int t,int l,int r,int *f,int dep) { if(l == r){*f = intmp[l];if(dep){f[1] = 0;}return;} int mid = (l+r)>>1,le = 1<<dep,i; _calc_inte(t<<1,l,mid,mou[dep],dep-1), _calc_inte(t<<1|1,mid+1,r,f,dep-1); memcpy(cpitmp,mou[dep],le<<1), memset(cpitmp+(le>>1),0,le<<1), NTT(cpitmp,le,1); memset(f+(le>>1),0,le<<1), NTT(f,le,1), NTT(pi[t<<1],le,1), NTT(pi[t<<1|1],le,1); for(i=0;i<le;i++)f[i] = ((LL)cpitmp[i]*pi[t<<1|1][i]+(LL)f[i]*pi[t<<1][i])%mod; NTT(f,le,-1); } void poly_inte(int *ptsx,int *ptsy,int cnt,int *f) { int lc,logc,i; for(lc=1,logc=0;lc<cnt;lc<<=1,logc++); memset(pool,0,(lc<<3)*(logc+1)); ptr = pool, src = ptsx, dst = intmp; _calc_pi(1,0,cnt-1,lc<<1); for(i=0;i<=logc;i++)mou[i] = ptr, ptr += 2<<i; for(i=1;i<=cnt;i++)intmp[i-1] = (LL)pool[i]*i%mod; _calc_eval(intmp,cnt,1,0,cnt-1,logc); for(i=0;i<cnt;i++)intmp[i] = (LL)ptsy[i]*invx(intmp[i])%mod; _calc_inte(1,0,cnt-1,f,logc); } int main() { NTT_Init(); return 0; } ```