[2017 Tsinghua training] spanning count

Topic Link

analysis

A Class Tree (the number of edges connected a set constant) contribution
\ [\ mathbb {Ans} ( \ {d_n \} | \ sum_id_i = 2 (n-1)) = \ prod_ia_i ^ {d_i} \ prod_id_i ^ m \ sum_ {i} d_i ^ m \
] introduced Prufer sequence set \ (D_i \) is the number of points (Unicom block) appears in the sequence, converting
\ [\ begin {aligned} \ mathbb {Ans} (\ {d_n \ } | \ sum_ {i} d_i = n-2) & = \ prod_ia_i ^ {d_i + 1} \ prod_i {(d_i + 1) ^ m} \ sum_ {i} (d_i + 1) ^ m \\ & = \ prod_ia_i ^ {d_i + 1}
(d_i + 1) ^ m \ sum_ {i} (d_i + 1) ^ m \\ \ end {aligned} \] then enumerate all combinations Prufer total answer
\ [\ begin {aligned} \ mathbb {Ans } & = \ sum _ {\ sum_id_i = n-2} \ frac {(n-2)!} {\ prod_id_i!} \ prod_ia_i ^ {d_i + 1} (d_i + 1) ^ m \ sum_ {i} (d_i + 1) ^ m \\ & = (n-2)! \ prod_ia_i \ sum _ {\ sum_id_i = n-2} \ prod_i \ frac {a_i ^ {d_i} (d_i + 1) ^ m} {d_i!} \ sum_i (d_i + 1) ^ {m} \\ & = (n-2)! \ prod_ia_i (\ sum _ {\ sum_id_i = n-2} \ sum_i \ frac {a_i ^ {d_i } (d_i + 1) ^ { 2m}} {d_i!} \ prod_ {i \ not = j} \ frac {a_j ^ {d_i} (d_j + 1) ^ m} {a_j!}) \ end {aligned} \]
G8 trouble ...... please the generating function
\ [A (x) = \ sum_i \ frac {x ^ i (i + 1) ^ {2m}} {i!} \\ B (x) = \ sum_i \ frac {x ^ i (i + 1) ^ m} {i!} \\ F
(x) = \ sum_iA (a_ix) \ prod_ {i \ not = j} B (a_jx) \] notes \ ([n-2] F (x) \) is \ (\ mathbb {Ans} \ ) very part (portion indicated in brackets). Then need to be addressed \ (F. (X) \)
\ [F. (X) = \ sum_i \ FRAC {A (a_ix)} {B (a_ix)} \ prod_ {I} B (a_ix) = \ sum_i \ FRAC {A (a_ix)} {B (a_ix
)} \ exp (\ sum_ {i} \ ln (B (a_ix))) \] in \ (\ ln \ exp \) CTV \ (a_ix \) whole variable processing \ (\ frac {a (x) } {B (x)} \) and \ (\ ln (B (x )) \) coefficients, then \ (a_ix \) substitution \ (X \) , to obtain \ (\ sum \ frac {A (a_ix)} {B (a_ix)} \) and \ (\ SUM \ LN (B (a_ix)) \) .

This process is essentially the same as two: function and \ (\ SUM \) of \ (I \) to the coefficients of a single function \ (I \) coefficient (constant) multiplied by \ (\ I sum_ka_k ^ \) .

Thus it involves a sequence of power and its generating function
\ [f (x) = \ sum_i \ sum_ja_j ^ ix ^ i = \ sum_i \ sum_j (a_ix) ^ j = \ sum_i \ frac {1} {1-a_ix } \\ g (x) = \ sum_i \ ln (\ frac {1} {1-a_ix}) = \ sum_i \ frac {-a_i} {1-a_ix} = - \ sum_i \ sum_ja_i ^ {j + 1} x ^ j \\ f (x) = nx \ times g (x) \\ g (x) = \ sum_i \ ln ((1-a_ix) ^ {- 1}) = - \ ln (\ prod_i1-a_ix) \]
for this \ (\ LN \) depending \ (X \) is variable rather than \ (a_ix \) , then the partition FFT processing \ (G (X) \) , provided \ (L \) is not less than \ (n-\) of the power of 2, can be roughly estimated as the complexity of the
\ [\ sum_d ^ {\ log L} \ frac {L} dd \ log d = L \ sum_d ^ {\ log L} \ log d = L \ log (\ log (L)
!) \] play table found \ (\ log (\ log ( L)!) \) representing \ (\ log (L) \ ) is slightly larger, much smaller than \ (\ log ^ 2 \) where the scale, so that complexity is approximately \ (O (n \ log n ) \)

Finally, slowly push back ......

achieve

There are many twists and turns ...... Los currently valley rank1

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N=200000;
const int MOD=998244353;

inline int qpow(int x,int y) {
    int c=1;
    for(; y; y>>=1,x=(ll)x*x%MOD) if(y&1) c=(ll)c*x%MOD;
    return c;
}

//------- POLYNOMIAL BEGIN -------
int w[N],rev[N],_inv[N],lmt;
inline void preDone(int len) {
    int l=0; lmt=1; _inv[1]=1;
    while(lmt<=len) lmt<<=1,l++;
    for(int i=0; i<lmt; ++i) {
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
        if(i>1) _inv[i]=(ll)_inv[MOD%i]*(MOD-MOD/i)%MOD;
    }
    int wlmt=qpow(3,(MOD-1)>>l),tmp=lmt>>1; w[tmp]=1;
    for(int i=tmp+1; i<lmt; ++i) w[i]=(ll)w[i-1]*wlmt%MOD;
    for(int i=tmp-1; i>0; --i) w[i]=w[i<<1];
    lmt=l;
}
inline void DFT(int a[],int len) {
    static unsigned long long tmp[N];
    int u=lmt-__builtin_ctz(len),T;
    for(int i=0; i<len; ++i) tmp[rev[i]>>u]=a[i];
    for(int m=1; m<len; m<<=1)
    for(int i=0,s=m<<1; i<len; i+=s)
    for(int j=0; j<m; ++j)
        T=tmp[i+j+m]*w[m+j]%MOD,tmp[i+j+m]=tmp[i+j]+MOD-T,tmp[i+j]+=T;
    for(int i=0; i<len; ++i) a[i]=tmp[i]%MOD;
}
inline void IDFT(int a[],int len) {
    reverse(a+1,a+len); DFT(a,len);
    ll T=MOD-(MOD-1)/len; 
    for(int i=0; i<len; ++i) a[i]=T*a[i]%MOD;
}
inline int getLen(int len) {
    return 1<<(32-__builtin_clz(len));
}
inline void getDer(int a[],int b[],int n) {
    for(int i=0; i<n-1; ++i) b[i]=(ll)(i+1)*a[i+1]%MOD; b[n-1]=0;
}
inline void getInt(int a[],int b[],int n) {
    for(int i=n-1; i>0; --i) b[i]=(ll)_inv[i]*a[i-1]%MOD; b[0]=0;
}
inline void getInv(int a[],int b[],int n) {
    static int tmp[N];
    if(n==1) {b[0]=qpow(a[0],MOD-2); return;}
    getInv(a,b,(n+1)>>1);
    int len=getLen(n<<1);
    for(int i=0; i<n; ++i) tmp[i]=a[i];
    for(int i=n; i<len; ++i) tmp[i]=0;
    DFT(tmp,len); DFT(b,len);
    for(int i=0; i<len; ++i) b[i]=(ll)b[i]*(2+MOD-(ll)b[i]*tmp[i]%MOD)%MOD;
    IDFT(b,len);
    for(int i=n; i<len; ++i) b[i]=0;
}
inline void getLn(int a[],int b[],int n) {
    static int tmp[N];
    getInv(a,tmp,n);
    getDer(a,b,n);
    int len=getLen(n<<1);
    DFT(tmp,len); DFT(b,len);
    for(int i=0; i<len; ++i) tmp[i]=(ll)b[i]*tmp[i]%MOD;
    IDFT(tmp,len);
    getInt(tmp,b,n);
    for(int i=n; i<len; ++i) b[i]=0;
    for(int i=0; i<len; ++i) tmp[i]=0;
}
inline void getExp(int a[],int b[],int n) {
    static int tmp[N];
    if(n==1) {b[0]=1; return;}
    getExp(a,b,(n+1)>>1);
    getLn(b,tmp,n);
    int len=getLen(n<<1);
    for(int i=0; i<n; ++i) tmp[i]=((i==0)+MOD-tmp[i]+a[i])%MOD;
    for(int i=n; i<len; ++i) tmp[i]=0;
    DFT(tmp,len); DFT(b,len);
    for(int i=0; i<len; ++i) b[i]=(ll)tmp[i]*b[i]%MOD;
    IDFT(b,len);
    for(int i=n; i<len; ++i) b[i]=0;
    for(int i=0; i<len; ++i) tmp[i]=0;
}
//------- POLYNOMIAL END -------

int n,m,con,a[N],d[20][N];
void solve(int l,int r,int p) {
    if(l==r) {
        d[p][0]=1;
        d[p][1]=MOD-a[l];
        return;
    }
    int mid=(l+r)>>1; 
    solve(l,mid,p);
    solve(mid+1,r,p+1);
    int len=getLen(r-l+1);
    for(int i=mid-l+2; i<len; ++i) d[p][i]=0;
    for(int i=r-mid+1; i<len; ++i) d[p+1][i]=0;
    DFT(d[p],len); DFT(d[p+1],len);
    for(int i=0; i<len; ++i) d[p][i]=(ll)d[p][i]*d[p+1][i]%MOD;
    IDFT(d[p],len);
}
int fc[N],fv[N];
int S[N],A[N],B[N],P[N],Q[N];

int main() {
    //freopen("filename.in","r",stdin);
    fc[0]=fc[1]=fv[0]=fv[1]=1;
    for(int i=2; i<N; ++i) fv[i]=(ll)fv[MOD%i]*(MOD-MOD/i)%MOD;
    for(int i=2; i<N; ++i) fv[i]=(ll)fv[i-1]*fv[i]%MOD;
    for(int i=2; i<N; ++i) fc[i]=(ll)fc[i-1]*i%MOD;
    
    scanf("%d%d",&n,&m); 
    preDone((n+1)*4); con=fc[n-2];
    for(int i=1; i<=n; ++i) scanf("%d",a+i),con=(ll)con*a[i]%MOD;
    solve(1,n,0); 
    getLn(d[0],S,getLen(n)); //改成二的幂次似乎能缓解数组清空问题……
    S[0]=n;
    for(int i=1; i<=n; ++i) S[i]=(MOD-(ll)S[i]*i%MOD)%MOD;

    for(int i=0; i<=n-2; ++i) {
        A[i]=(ll)fv[i]*qpow(i+1,2*m)%MOD;
        B[i]=(ll)fv[i]*qpow(i+1,m)%MOD;
    }
    getInv(B,P,n-1);
    getLn(B,Q,n-1);
    int len=getLen(n<<1);
    DFT(A,len); DFT(P,len);
    for(int i=0; i<len; ++i) P[i]=(ll)A[i]*P[i]%MOD;
    IDFT(P,len);
    for(int i=n-1; i<len; ++i) P[i]=0;
    for(int i=0; i<=n-2; ++i) {
        P[i]=(ll)P[i]*S[i]%MOD;
        Q[i]=(ll)Q[i]*S[i]%MOD;
    }
    memset(B,0,sizeof B); //这儿也是……
    getExp(Q,B,n-1);
    DFT(P,len); DFT(B,len);
    for(int i=0; i<len; ++i) P[i]=(ll)P[i]*B[i]%MOD;
    IDFT(P,len);
    
    printf("%lld\n",(ll)con*P[n-2]%MOD);
    return 0;
}

Guess you like

Origin www.cnblogs.com/nosta/p/11079216.html