MnZn 求调三模 NTT
查看原帖
MnZn 求调三模 NTT
420129
Nt_Tsumiki楼主2025/2/5 19:20

RT

三模 NTT 能过任意模板子,剩下的直接从 P6800 粘过来的,能过样例,但是全 WA。

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

#define N 2400005
#define LL long long

inline int R() {
    int x=0; bool f=0; char c=getchar();
    while (!isdigit(c)) f|=(c=='-'),c=getchar();
    while (isdigit(c)) x=x*10+c-'0',c=getchar();
    return f?-x:x;
}

template<typename T>
void W(T x,char Extra=0) {
    if (x<0) putchar('-'),x=-x; if (x>9) W(x/10);
    putchar(x%10+'0'); if (Extra) putchar(Extra);
}

using namespace std;
int n,c,m; const int P=1e9+7;

inline LL quickpow(LL a,int k,LL P) {
    LL res=1;
    while (k) {
        if (k&1) res=res*a%P;
        a=a*a%P,k>>=1;
    }
    return res;
}
const LL MOD1=998244353,MOD2=1004535809,MOD3=469762049,MOD12=1ll*MOD1*MOD2;
const LL inv1=quickpow(MOD1,MOD2-2,MOD2),inv2=quickpow(MOD12%MOD3,MOD3-2,MOD3);

struct Int {
    LL A,B,C;
    inline Int(LL x=0) { A=B=C=x; }
    inline Int(LL a,LL b,LL c) { A=a,B=b,C=c; }

    inline Int operator*(const Int &tmp) const { return {A*tmp.A%MOD1,B*tmp.B%MOD2,C*tmp.C%MOD3}; }
    inline Int operator+(const Int &tmp) const { return {(A+tmp.A)%MOD1,(B+tmp.B)%MOD2,(C+tmp.C)%MOD3}; }
    inline Int operator-(const Int &tmp) const { return {(A-tmp.A+MOD1)%MOD1,(B-tmp.B+MOD2)%MOD2,(C-tmp.C+MOD3)%MOD3}; }
    inline LL get() {
        LL tmp=(B-A+MOD2)%MOD2*inv1%MOD2*MOD1+A;
        return ((C-tmp%MOD3+MOD3)%MOD3*inv2%MOD3*(MOD12%P)%P+tmp)%P;
    }
};

Int G={3,3,3},iG={quickpow(3,MOD1-2,MOD1),quickpow(3,MOD2-2,MOD2),quickpow(3,MOD3-2,MOD3)},w[22],iw[22];

int to[N];

void init() {
    for (int i=0;i<22;i++) w[i]=Int(quickpow(G.A,(MOD1-1)/(1<<(i+1)),MOD1),quickpow(G.B,(MOD2-1)/(1<<(i+1)),MOD2),quickpow(G.C,(MOD3-1)/(1<<(i+1)),MOD3));
    for (int i=0;i<22;i++) iw[i]=Int(quickpow(iG.A,(MOD1-1)/(1<<(i+1)),MOD1),quickpow(iG.B,(MOD2-1)/(1<<(i+1)),MOD2),quickpow(iG.C,(MOD3-1)/(1<<(i+1)),MOD3));
}

void NTT(vector<Int> &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) {
        Int wk=(op==1?w[__lg(i)]:iw[__lg(i)]);
        for (int j=0;j<n;j+=(i<<1)) {
            Int w={1,1,1};
            for (int k=0;k<i;k++,w=w*wk) {
                Int pe=A[j+k],po=w*A[i+j+k];
                A[j+k]=pe+po,A[i+j+k]=pe-po;
            }
        }
    }
}

vector<Int> operator*(vector<Int> f,vector<Int> g) {
    int m=(f.size()-1+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];
    NTT(f,n,-1); f.resize(m+1);
    Int invn={quickpow(n,MOD1-2,MOD1),quickpow(n,MOD2-2,MOD2),quickpow(n,MOD3-2,MOD3)};
    for (int i=0;i<=m;i++) f[i]=f[i]*invn;
    f.resize(m+1);
    return f;
}

vector<Int> f,g;

int main() {
    n=R(),c=R(),m=R(); f.resize(n); g.resize(n+m-1); init();
    int invc=quickpow(c,P-2,P);
    for (int i=0;i<n;i++) f[i]=Int(quickpow(invc,(1ll*i*(i-1)/2)%(P-1),P))*R();
    for (int i=0;i<n+m-1;i++) g[i]=Int(quickpow(c,(1ll*i*(i-1)/2)%(P-1),P));
    reverse(f.begin(),f.end()); f=f*g;
    for (int i=0;i<m;i++) W(f[n-1+i].get()*quickpow(invc,(1ll*i*(i-1)/2)%(P-1),P)%P," \n"[i==m-1]);
    return 0;
}
2025/2/5 19:20
加载中...