CF Gym102028G Shortest Paths on Random Forests

Portal

This requires the desired title, is the total weight (not all contributions to the same point of the communication block + the same contribution to the communication block point) / Total embodiment (forest number)

First seek number, forest tree composition formed from a pile which, according purfer sequence, a \ (\ n-) the number of points for a labeled tree \ (n-2-n-^ {} \) , reference point because then there can be considered EGF, EGF-tree is set \ (F. (X) \) , then the generating function of the forest \ (e ^ {F (x )} \)

Then the contribution not to block the same communication point, which is equal to not block the same communication point number \ (* m ^ 2 \) , and not in the same communication block and the number of points equal to the total number of points \ (- \) in communication with a block size of a point to consider the number of enumeration communication block, then the size of \ (n-\) contributed by the communication block is \ (n ^ {n-2 } \ binom { }} {2 n-\) , and then multiplied by the communication block also appear many times, and that the remaining part is a forest, so this mess and EGF volume generation function before the forest on the line

Finally, the contribution of the same point of the communication block, square somewhat difficult process, consider the conversion of about \ [\ begin {aligned} \ sum_ {i = 1} ^ {n} \ sum_ {j = i + 1} ^ {n} dis (i, j) ^ 2 & = \ sum_ {i = 1} ^ {n} \ sum_ {j = i + 1} ^ {n} (\ sum _ {(x, y) \ in (i, j)} 1 ) ^ 2 \\ & = \ sum_ {i = 1} ^ {n} \ sum_ {j = i + 1} ^ {n} \ sum _ {(x1, y1) \ in (i, j)} \ sum_ { (x2, y2) \ in ( i, j)} 1 \ end {aligned} \] it is enumerated two sides on the path, and then combined. we exchanged order of enumeration, the enumeration on the first two side, and then consider how many path also includes two edges. If the two sides are the same, it will communicate with the host communication block into two blocks, otherwise it will be divided into three blocks communication to the former, enumeration two communication block size \ (sz_1, sz_2 \) , and then enumerate two paths starting, contribution \ (sz_1sz_2 \) , and then enumerate the intersection of these two sides and two blocks communication, contribution \ (sz_1sz_2 \) , so the total contribution \ ((sz_1sz_2) ^ 2 \) . then three blocks communication contribution is similar, i.e. \ ((sz_1sz_2sz_3) ^ 2 \) . as above, this volume into an upper and EGF forest before generating function. Note however that the case of three communication block, we enumerate the two sides are The order, so \ (* 2 \) ; then the calculation of the time will \ ((i, j) \ ) contributions and \ ((j, i) \ ) contributions are considered to come, so this part of the contribution to be\(/2\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double

using namespace std;
const int N=1e6+10,M=(1<<20)+10,mod=998244353,inv2=499122177;
LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
namespace ct2
{
    int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
    int ginv(int a){return fpow(a,mod-2);}
    int rdr[M],inv[M],p1[M],p2[M],p3[M],p4[M],p5[M];
    void ntt(int *a,int n,bool op)
    {
        int l=0,x,y;
        while((1<<l)<n) ++l;
        for(int i=0;i<n;++i)
        {
            rdr[i]=(rdr[i>>1]>>1)|((i&1)<<(l-1));
            if(i<rdr[i]) swap(a[i],a[rdr[i]]);
        }
        for(int i=1;i<n;i<<=1)
        {
            int ww=fpow(op?3:332748118,(mod-1)/(i<<1));
            for(int j=0;j<n;j+=i<<1)
                for(int k=0,w=1;k<i;++k,w=1ll*w*ww%mod)
                    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(!op) for(int i=0,w=ginv(n);i<n;++i) a[i]=1ll*a[i]*w%mod;
    }
    void polyder(int *aa,int *bb,int n)
    {
        for(int i=0;i<n-1;++i) bb[i]=1ll*aa[i+1]*(i+1)%mod;
        bb[n-1]=bb[n]=0;
    }
    void polying(int *aa,int *bb,int n)
    {
        for(int i=1;i<n;++i) bb[i]=1ll*aa[i-1]*inv[i]%mod;
        bb[0]=0;
    }
    void polyinv(int *aa,int *bb,int n)
    {
        if(n==1){bb[0]=ginv(aa[0]);return;}
        polyinv(aa,bb,n>>1);
        for(int i=0;i<n;++i) p1[i]=aa[i],p2[i]=bb[i];
        ntt(p1,n<<1,1),ntt(p2,n<<1,1);
        for(int i=0;i<n<<1;++i) p1[i]=1ll*p1[i]*p2[i]%mod*p2[i]%mod;
        ntt(p1,n<<1,0);
        for(int i=0;i<n;++i) bb[i]=((bb[i]+bb[i])%mod-p1[i]+mod)%mod;
        for(int i=0;i<n<<1;++i) p1[i]=p2[i]=0;
    }
    void polyln(int *aa,int *bb,int n)
    {
        polyder(aa,p3,n),polyinv(aa,p4,n);
        ntt(p3,n<<1,1),ntt(p4,n<<1,1);
        for(int i=0;i<n<<1;++i) p3[i]=1ll*p3[i]*p4[i]%mod;
        ntt(p3,n<<1,0);
        polying(p3,bb,n);
        for(int i=0;i<n<<1;++i) p3[i]=p4[i]=0;
    }
    void polyexp(int *aa,int *bb,int n)
    {
        if(n==1){bb[0]=1;return;}
        polyexp(aa,bb,n>>1);
        polyln(bb,p5,n);
        for(int i=0;i<n;++i) p1[i]=bb[i],p5[i]=(-p5[i]+aa[i]+mod)%mod;
        p5[0]=(p5[0]+1)%mod;
        ntt(p1,n<<1,1),ntt(p5,n<<1,1);
        for(int i=0;i<n<<1;++i) p1[i]=1ll*p1[i]*p5[i]%mod;
        ntt(p1,n<<1,0);
        for(int i=0;i<n;++i) bb[i]=p1[i];
        for(int i=0;i<n<<1;++i) p1[i]=p5[i]=0;
    }
    int fac[N],iac[N],aa[M],f[M],dotf[M],g[M],h[M],h2[M],h3[M],hh[M];
    int C(int n,int m){return m<0||n<m?0:1ll*fac[n]*iac[m]%mod*iac[n-m]%mod;}
    void wk()
    {
        int nn=200010,len=1<<18;
        inv[0]=inv[1]=1;
        for(int i=2;i<=nn;++i) inv[i]=(mod-1ll*(mod/i)*inv[mod%i]%mod)%mod;
        fac[0]=1;
        for(int i=1;i<=nn;++i) fac[i]=1ll*fac[i-1]*i%mod;
        iac[nn]=ginv(fac[nn]);
        for(int i=nn;i;--i) iac[i-1]=1ll*iac[i]*i%mod;
        aa[1]=1;
        for(int i=2;i<=nn;++i) aa[i]=1ll*fpow(i,i-2)*iac[i]%mod;
        polyexp(aa,f,len);
        f[0]=1;
        len<<=1;
        for(int i=0;i<=nn;++i) dotf[i]=f[i];
        ntt(dotf,len,1);
        for(int i=2;i<=nn;++i) g[i]=1ll*C(i,2)*fpow(i,i-2)%mod*iac[i]%mod;
        ntt(g,len,1);
        for(int i=0;i<len;++i) g[i]=1ll*g[i]*dotf[i]%mod;
        ntt(g,len,0);
        h[1]=1;
        for(int i=2;i<=nn;++i) h[i]=1ll*i*i%mod*fpow(i,i-2)%mod*iac[i]%mod;
        ntt(h,len,1);
        for(int i=0;i<len;++i) h2[i]=1ll*h[i]*h[i]%mod;
        ntt(h2,len,0);
        for(int i=1;i<=nn;++i) hh[i]=1ll*h2[i]*inv2%mod;
        for(int i=nn+1;i<len;++i) h2[i]=0;
        ntt(h2,len,1);
        for(int i=0;i<len;++i) h3[i]=1ll*h2[i]*h[i]%mod;
        ntt(h3,len,0);
        for(int i=1;i<=nn;++i) hh[i]=(hh[i]+h3[i])%mod;
        ntt(hh,len,1);
        for(int i=0;i<len;++i) hh[i]=1ll*hh[i]*dotf[i]%mod;
        ntt(hh,len,0);
        for(int i=1;i<=nn;++i)
        {
            f[i]=1ll*f[i]*fac[i]%mod;
            g[i]=1ll*g[i]*fac[i]%mod;
            hh[i]=1ll*hh[i]*fac[i]%mod;
        }
        int T=rd();
        while(T--)
        {
            int n=rd(),m=rd();
            m=1ll*m*m%mod;
            int ans=(1ll*m*(1ll*f[n]*C(n,2)%mod-g[n]+mod)%mod+1ll*hh[n])%mod;
            ans=1ll*ans*ginv(f[n])%mod;
            printf("%d\n",ans);
        }
    }
}

int main()
{
    ct2::wk();
    return 0;
}

Guess you like

Origin www.cnblogs.com/smyjr/p/11029586.html