LOJ2320 "Tsinghua training 2017" spanning tree count

Because I really did not learn a chicken dish that power rise power fall a theory here is completely ordinary polynomial approach.

If there is big brother is willing to tell me that a power rise power fall things, be grateful orz!

First, it is conceivable prufer sequence, if not, then you can turn left Baidu.

We answer in the form of written prufer sequence, so his contribution is fixed, where $ d_i $ $ i $ represents the number appears.

$ans = (n-2)! \prod_{i=1}^n \frac{a_i^{d_i+1}}{d_i!}$

Brought in the original persimmon

$ans = \sum_{\sum d_i = n-2} (n-2)! \sum_{i=1}^n a_i^{d_i+1} d_i^m\prod_{j=1}\frac{d_j^m}{d_j!}$

To put forward the same factor

$ans =(n-2)! \prod_{i=1}^n a_i \sum_{\sum d_i = n-2} \sum_{i=1}^n a_i^{d_i} d_i^m\prod_{j=1}\frac{d_j^m}{d_j!}$

Consider back

$ans' = \sum_{\sum d_i = n-2} \sum_{i=1}^n a_i^{d_i} d_i^m\prod_{j=1}\frac{d_j^m}{d_j!}$

In order to facilitate the generating function written form, such into the persimmon

$ans' = \sum_{\sum d_i = n-2} \sum_{i=1}^n \frac{a_i^{d_i} d_i^{2m}}{d_i!}\prod_{j=1,j\neq i}\frac{d_j^m}{d_j!} $

Assume

$A(x)=\sum_{i=0}^n \frac{i^{2m}}{i!} x^i$

$B(x)=\sum_{i=0}^n \frac{i^m}{i!} x^i$

Bring them into

$ans '=\sum_{i=1}^n A(a_i) \prod{j=1,j\neq i}^n B(a_j) \\ = \sum_{i=1}^n \frac{A}{B}(a_i) \prod_{j=1}^n B(a_j)$

For $ \ prod B (a_i) $ The common routines, written $ exp (\ sum ln (B (a_i))) $ course $ \ frac {A} {B} $ is such a process.

Then we met more often, seeking $ \ sum_ {i = 1} {n} a_i ^ k $ is seeking power and the number of columns.

This thing can poke here: qwq  (amount requires a password, if you need, then you can poke my QQ)

Here's a brief talk about, is that we have $ F (x) = \ sum (a_1 ^ i + ... + a_n ^ i) x ^ i $ can be turned into this $ F (x) = \ sum (a_ix + ... + a_i ^ nx ^ n} $ further written as $ F (x) = \ sum \ frac {1} {1-a_ix} $

We let $ G (x) = \ prod (1-a_ix) $ it is $ F = -ln '(G) $

For $ G $, we can direct the partition FFT, then you can poly_ln to seek F

The rest of the family is to write a polynomial barrel on it.

Ah, polynomial really interesting.

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define mdn 998244353
#define G 3
#define N 400100
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
int fac[N],inv[N];
int Inv(int x){return 1ll*inv[x]*fac[x-1]%mdn;}
void upd(int &x,int y){x+=x+y>=mdn?y-mdn:y;}
int ksm(int bs,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)    ans=1ll*ans*bs%mdn;
        bs=1ll*bs*bs%mdn; mi>>=1;
    }
    return ans;
}
int r[N];
int init(int n)
{
    int l=0,lim=1;
    while(lim<n)    lim<<=1,l++;
    for(int i=0;i<lim;i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
    return lim;
}
void ntt(int *a,int lim,int f)
{
    for(int i=0;i<lim;i++)    if(r[i]>i)
        swap(a[r[i]],a[i]);
    for(int k=2,mid=1;k<=lim;k<<=1,mid<<=1)
    {
        int Wn=ksm(G,(mdn-1)/k); if(f)    Wn=ksm(Wn,mdn-2);
        for(int w=1,i=0;i<lim;i+=k,w=1)    for(int j=0;j<mid;j++,w=1ll*w*Wn%mdn)
        {
            int x=a[i+j],y=1ll*w*a[i+mid+j]%mdn;
            a[i+j]=(x+y)%mdn; a[i+mid+j]=(mdn+x-y)%mdn;
        }
    }
    if(f)    for(int kinv=ksm(lim,mdn-2),i=0;i<lim;i++)
        a[i]=1ll*a[i]*kinv%mdn;
}
int poly_mul(int *a,int *b,int *c,int n)
{
    int lim=init(n<<1);
    ntt(a,lim,0); ntt(b,lim,0);
    for(int i=0;i<lim;i++)    c[i]=1ll*a[i]*b[i]%mdn;
    ntt(c,lim,1); return lim;
}
int tmp[N];
void poly_inv(int *a,int *ans,int n)
{
    if(n==1){ans[0]=ksm(a[0],mdn-2); return;}
    int mid=n+1>>1; poly_inv(a,ans,mid);
    int lim=init(n<<1);
    for(int i=0;i<n;i++)    tmp[i]=a[i];
    for(int i=n;i<lim;i++)    tmp[i]=0;
    ntt(tmp,lim,0); ntt(ans,lim,0);
    for(int i=0;i<lim;i++)
        ans[i]=(2ll-1ll*tmp[i]*ans[i]%mdn+mdn)*ans[i]%mdn;
    ntt(ans,lim,1);
    for(int i=n;i<lim;i++)    ans[i]=0;
}
int tmp2[N];
void poly_ln(int *a,int *ans,int n)
{
    poly_inv(a,tmp2,n);
    for(int i=0;i<n;i++)    ans[i]=1ll*a[i+1]*(i+1)%mdn;
    int lim=poly_mul(tmp2,ans,tmp2,n); tmp2[n-1]=0;
    for(int i=1;i<n;i++)    ans[i]=1ll*tmp2[i-1]*Inv(i)%mdn,tmp2[i-1]=0;
    for(int i=n;i<lim;i++)    ans[i]=tmp2[i]=0;
    ans[0]=0;
}
int tmp3[N],tmp4[N];
void poly_exp(int *a,int *ans,int n)
{
    if(n==1){ans[0]=1; return;}
    int mid=n+1>>1; poly_exp(a,ans,mid);
    for(int i=0;i<(n<<1);i++)    tmp2[i]=tmp3[i]=0;
    for(int i=0;i<n;i++)    tmp4[i]=a[i]; poly_ln(ans,tmp3,n);
    int lim=init(n<<1);
    ntt(tmp3,lim,0); ntt(tmp4,lim,0); ntt(ans,lim,0);
    for(int i=0;i<lim;i++)
        ans[i]=1ll*(tmp4[i]-tmp3[i]+1+mdn)%mdn*ans[i]%mdn;
    ntt(ans,lim,1);
    for(int i=n;i<lim;i++)    ans[i]=tmp4[i]=0;
}
int tmp5[N],tmp6[N];
void solve(int *a,int l,int r)
{
    if(l==r)    return;
    int mid=l+r>>1;
    solve(a,l,mid); solve(a,mid+1,r);
    int d=r-l+1;
    for(int i=l;i<=mid;i++)    tmp5[i-l+1]=a[i];
    for(int i=mid+1;i<=r;i++)    tmp6[i-mid]=a[i];
    tmp5[0]=tmp6[0]=1;
    int lim=poly_mul(tmp5,tmp6,tmp5,d);
    for(int i=0;i<d;i++)    a[l+i]=tmp5[i+1];
    for(int i=0;i<=lim;i++)    tmp5[i]=tmp6[i]=0;
}
void prework(int n)
{
    n++; fac[0]=1;
    for(int i=1;i<=n;i++)    fac[i]=1ll*fac[i-1]*i%mdn;
    inv[n]=ksm(fac[n],mdn-2);
    for(int i=n;i;i--)    inv[i-1]=1ll*inv[i]*i%mdn;
}
int a[N],f[N],n,m,g[N],A[N],B[N],in[N],fr[N],ls[N];
int main()
{
    n=read(),m=read(); prework(n);
    for(int i=1;i<=n;i++)    a[i]=read(),f[i]=(mdn-a[i])%mdn;
    solve(f,1,n); f[0]=1; poly_ln(f,g,n+1);
    for(int i=0;i<=n;i++)    f[i]=1ll*g[i+1]*(i+1)%mdn;
    for(int i=n;i;i--)    f[i]=(-f[i-1]+mdn)%mdn; f[0]=n;
    for(int i=0;i<=n;i++)
    {
        A[i]=1ll*ksm(i+1,2*m)*inv[i]%mdn;
        B[i]=1ll*ksm(i+1,m)*inv[i]%mdn;
    }
    int lim=init(n<<1|1);
    poly_ln(B,g,n+1); poly_inv(B,in,n+1);
    for(int i=0;i<n;i++)    g[i]=1ll*g[i]*f[i]%mdn;
    for(int i=n;i<lim;i++)    g[i]=in[i]=0;
    poly_exp(g,ls,n);
    for(int i=n;i<lim;i++)    ls[i]=0;
    poly_mul(A,in,fr,n);
    for(int i=0;i<n;i++)    fr[i]=1ll*fr[i]*f[i]%mdn;
    for(int i=n;i<lim;i++)    fr[i]=0;
    poly_mul(fr,ls,f,n);
    int ans=fac[n-2];
    for(int i=1;i<=n;i++)    ans=1ll*ans*a[i]%mdn;
    ans=1ll*ans*f[n-2]%mdn;
    printf("%d\n",ans);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/hanyuweining/p/11594258.html