MnZn 求助多项式全家桶
  • 板块学术版
  • 楼主Nt_Tsumiki
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/9/14 18:52
  • 上次更新2024/9/14 19:15:03
查看原帖
MnZn 求助多项式全家桶
420129
Nt_Tsumiki楼主2024/9/14 18:52

polyln() 中有一句给 D 赋初始长度,加上后,在 polyinv() 后跑出来是全零,去掉就没事,求助一下这是为啥。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

#define LL long long
#define MOD 998244353
#define N 4000005

using namespace std;
int n,m;

LL quickpow(LL a,int k) {
    LL res=1;
    while (k) {
        if (k&1) res=res*a%MOD;
        a=a*a%MOD,k>>=1;
    }
    return res;
} LL G=3,iG=quickpow(G,MOD-2);

namespace Poly {
    int to[N];

    void NTT(vector<LL> &A,int n,int op) {
        for (int i=0;i<n;i++)
            if (i<to[i]) swap(A[i],A[to[i]]);
        for (int i=1;i<n;i<<=1)
            for (int j=0;j<n;j+=(i<<1)) {
                LL w=1,wk=quickpow(op==1?G:iG,(MOD-1)/(i<<1));
                for (int k=0;k<i;k++,w=w*wk%MOD) {
                    LL pe=A[j+k],po=w*A[i+j+k]%MOD;
                    A[j+k]=(pe+po)%MOD,A[i+j+k]=(pe-po+MOD)%MOD;
                }
            }
    }

    vector<LL> operator*(vector<LL> f,vector<LL> g) {
        int m=(int)f.size()-1+(int)g.size()-1,n=1,K=0;
        while (n<=m) n<<=1,K++;
        for (int i=0;i<n;i++)
            to[i]=(to[i>>1]>>1)|((i&1)<<(K-1));
        f.resize(n); g.resize(n);
        NTT(f,n,1); NTT(g,n,1);
        for (int i=0;i<n;i++)
            f[i]=f[i]*g[i]%MOD;
        NTT(f,n,-1);
        LL invn=quickpow(n,MOD-2);
        for (int i=0;i<=m;i++) f[i]=f[i]*invn%MOD;
        f.resize(m+1);
        return f;
    }

    void polyde(vector<LL> &A,vector<LL> &B,int n) {
        for (int i=0;i<n-1;i++)
            B[i]=(i+1)*A[i+1]%MOD;
        B[n-1]=0;
    }

    void polyinvde(vector<LL> &A,vector<LL> &B,int n) {
        for (int i=1;i<n;i++)
            B[i]=A[i-1]*quickpow(i,MOD-2)%MOD;
        B[0]=0;
    }

    void polyinv(vector<LL> &A,vector<LL> &B,int n) {
        if (n==1)
            return B.resize(1,quickpow(A[0],MOD-2)),void();
        polyinv(A,B,(n+1)>>1);
        int m=1,K=0;
        while (m<(n<<1)) m<<=1,K++;
        for (int i=0;i<m;i++)
            to[i]=(to[i>>1]>>1)|((i&1)<<(K-1));
        vector<LL> C(m,0);
        for (int i=0;i<n;i++) C[i]=A[i];
        B.resize(m);
        NTT(C,m,1); NTT(B,m,1);
        for (int i=0;i<m;i++)
            B[i]=(2*B[i]%MOD-C[i]*B[i]%MOD*B[i]%MOD+MOD)%MOD;
        NTT(B,m,-1);
        LL invm=quickpow(m,MOD-2);
        for (int i=0;i<n;i++) B[i]=B[i]*invm%MOD;
        B.resize(n);
    }

    void polyln(vector<LL> &A,vector<LL> &B,int n) {
        int m=1,K=0;
        while (m<(n<<1)) m<<=1,K++;
        for (int i=0;i<m;i++)
            to[i]=(to[i>>1]>>1)|((i&1)<<(K-1));
        vector<LL> C(m,0),D(m,0);
        polyde(A,C,n); polyinv(A,D,n);
        C.resize(m); D.resize(m);
        NTT(C,m,1); NTT(D,m,1);
        for (int i=0;i<m;i++)
            C[i]=C[i]*D[i]%MOD;
        NTT(C,m,-1);
        LL invm=quickpow(m,MOD-2);
        for (int i=0;i<n;i++) C[i]=C[i]*invm%MOD;
        C.resize(n); B.resize(n);
        polyinvde(C,B,n);
    }
}
using namespace Poly;
vector<LL> f,g;

int main() {
    scanf("%d",&n); f.resize(n);
    for (int i=0;i<n;i++) scanf("%lld",&f[i]);
    polyln(f,g,n);
    for (int i=0;i<n;i++) printf("%lld ",g[i]);
    printf("\n");
    return 0;
}
2024/9/14 18:52
加载中...