多项式全家桶

Posted jrf123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式全家桶相关的知识,希望对你有一定的参考价值。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define mod 998244353
using namespace std;
int n,a[600100],b[600100],ina[600100],lna[600100],lnc[600100],sqa[600100],sqb[600100],exa[600100],exb[600100],poa[600100],pob[600100],pos[600100];
int read()
{
    int aa=0,bb=1;char cc=getchar();
    while(cc>9||cc<0){if(cc==-) bb=-1;cc=getchar();}
    while(cc>=0&&cc<=9){aa=(aa<<3)+(aa<<1)+(cc^0);cc=getchar();}
    return aa*bb;
}
int quick(int x,int p)
{
    int as=1;
    while(p){
        if(p&1) as=1ll*as*x%mod;
        x=1ll*x*x%mod;p>>=1;
    }
    return as;
}
void ntt(int *a,int len,int opt)
{
    for(int i=0;i<len;i++) if(i<pos[i]) swap(a[i],a[pos[i]]);
    for(int i=1;i<len;i<<=1){
        int step=i<<1,wn=quick(3,(mod-1)/step);
        for(int j=0;j<len;j+=step){
            int w=1;
            for(int k=0;k<i;k++,w=1ll*w*wn%mod){
                int x=a[j+k],y=1ll*a[j+k+i]*w%mod;
                a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
            }
        }
    }
    if(opt){
        reverse(a+1,a+len);int inv=quick(len,mod-2);
        for(int i=0;i<len;i++) a[i]=1ll*a[i]*inv%mod;
    }
}
void getderiv(int n,int *a,int *b)
{
    for(int i=1;i<n;i++) b[i-1]=1ll*a[i]*i%mod;
    b[n-1]=0;
}
void getinteg(int n,int *a,int *b)
{
    for(int i=1;i<n;i++) b[i]=1ll*a[i-1]*quick(i,mod-2)%mod;
    b[0]=0;
}
void getinv(int n,int *a,int *b)
{
    if(n==1){b[0]=quick(a[0],mod-2);return;}
    getinv((n+1)>>1,a,b);
    int lenth=1,bit=0;
    while(lenth<=n+n+n) lenth<<=1,bit++;
    for(int i=0;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1);
    for(int i=0;i<n;i++) ina[i]=a[i];
    for(int i=n;i<lenth;i++) ina[i]=0;
    ntt(ina,lenth,0);ntt(b,lenth,0);
    for(int i=0;i<lenth;i++) b[i]=(2ll*b[i]%mod-1ll*ina[i]*b[i]%mod*b[i]%mod+mod)%mod;
    ntt(b,lenth,1);
    for(int i=n;i<lenth;i++) b[i]=0;
}
void getln(int n,int *a,int *b)
{
    getderiv(n,a,lna);
    getinv(n,a,lnc);
    int lenth=1,bit=0;
    while(lenth<=n+n) lenth<<=1,bit++;
    for(int i=0;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1);
    ntt(lna,lenth,0);ntt(lnc,lenth,0);
    for(int i=0;i<lenth;i++) lna[i]=1ll*lna[i]*lnc[i]%mod;
    ntt(lna,lenth,1);getinteg(n,lna,b);
    for(int i=0;i<lenth;i++) lna[i]=0,lnc[i]=0;
}
void getsqrt(int n,int *a,int *b)
{
    if(n==1){b[0]=1;return;}
    getsqrt((n+1)>>1,a,b);
    getinv(n,b,sqb);
    int lenth=1,bit=0;
    while(lenth<=n+n+n) lenth<<=1,bit++;
    for(int i=0;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1);
    for(int i=0;i<n;i++) sqa[i]=a[i];
    for(int i=n;i<lenth;i++) sqa[i]=0;
    ntt(b,lenth,0);ntt(sqa,lenth,0);ntt(sqb,lenth,0);int inv=quick(2,mod-2);
    for(int i=0;i<lenth;i++) b[i]=(1ll*b[i]*b[i]%mod+sqa[i])%mod*sqb[i]%mod*inv%mod;
    ntt(b,lenth,1);
    for(int i=n;i<lenth;i++) b[i]=0;
    for(int i=0;i<lenth;i++) sqb[i]=0;
}
void getexp(int n,int *a,int *b)
{
    if(n==1){b[0]=1;return;}
    getexp((n+1)>>1,a,b);
    getln(n,b,exb);
    int lenth=1,bit=0;
    while(lenth<=n+n) lenth<<=1,bit++;
    for(int i=1;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1);
    for(int i=0;i<n;i++) exb[i]=(a[i]-exb[i]+mod)%mod;exb[0]++;
    for(int i=n;i<lenth;i++) exb[i]=0;
    ntt(exb,lenth,0);ntt(b,lenth,0);
    for(int i=0;i<lenth;i++) b[i]=1ll*b[i]*exb[i]%mod;
    ntt(b,lenth,1);
    for(int i=n;i<lenth;i++) b[i]=0;
}
void getpow(int n,int *a,int *b,int k)
{
    getln(n,a,poa);
    for(int i=0;i<n;i++) pob[i]=1ll*poa[i]*k%mod;
    getexp(n,pob,b);
    int lenth=1,bit=0;
    while(lenth<=n) lenth<<=1,bit++;
    for(int i=n;i<lenth;i++) b[i]=0;
    for(int i=0;i<lenth;i++) poa[i]=0,pob[i]=0;
}
int main()
{
    n=read();
    for(int i=0;i<n;i++) a[i]=read();
    getsqrt(n,a,b);
    for(int i=0;i<n;i++) printf("%d ",b[i]);
    return 0;
}

 

啥都不会只会板子(现在连板子都不会了

以上是关于多项式全家桶的主要内容,如果未能解决你的问题,请参考以下文章

多项式全家桶(持续更新中)

学习笔记多项式全家桶(包含全套证明)

多项式全家桶

多项式全家桶

多项式全家桶

多项式全家桶