Codechefシェフは、ツリーを切り取り

SoftBrands SoftBrandsとき、彼のルーチンは、もはや日常の問題で終わり、で

まず、我々は正方形のブロックのサイズを連結および形質転換し、その等価見出される通信ポイント数を、これはに変換することができるエッジの数(距離)の接続点と

したがって、我々は最初に考える\(私は\)日、ポイント\((x、y)は\ ) 貢献作り出すことができるのであれば、接続は、それらの縁を壊さなかった場合にのみ貢献のように:

\ [\ FRAC {(N-1- \ operatorname {DIS}(X、Y))^ {\下線I}} {(N-1)^ {\下線I} \]

だから我々は、すべてこの事を見つけるの点から同じ距離が同じであるので、我々は直接、距離の全て数えることができます\(I(私は[中\ 0、N-1])\) 番号にポイントをnum_i(\ \)

一日のために、次に考える\(I \)列挙距離\(D \)ポイントの、そして:

\ [ans_i = \ sum_ {D = 0} ^ {N-1} \ FRAC {(ND-1)!\回(NI-1)!\回num_d} {(NDI-1)!\回(N- 1)!} \]

どうやら畳み込みの形で、私たちは聞かせて\(A(X)=(Ni基。1)!\タイムズnum_i、B(X)= \ {I}。1 FRAC {!} \) コンボリューション後に戻って服用しないでください変数は、その後、逆にすることができます

だから、残りの二つの問題があり、距離は\(私は\)どのように需要の数をポイント?

まず、分割点と征服し、非常にナイーブなアイデアがあるすべての単一のサブツリー情報の後に暴力を横断するFFTのマージ

しかし、この出会いの菊マップ直接GGので、我々はできると除外

ルートパスとして各区画の中心にすべての長さの個数を検索し、次にツリーに同一のサブ部分、および同じコンボリューション前の正方形を算出する方法で繰り返し減算

一つの最後の質問、弾性率よりNTTモジュラス話題のがんと人々、我々は書きください3モードNTTの

しかし、FFTの発見が書かれているので、我々が直接前に解体係数はうまくやって

PS:私は弱すぎないのですMTTので、彼は2と4 DFT最も暴力的、大きな定数IDFTバージョン4、それの複雑さを書いた\(\ \をログ)これを見ます

最後に、1.36sを走っ開くために注意を払うlong longと、long double

コード

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cmath>
#define int LL
#define RI register int
#define CI const int&
#define Tp template <typename T>
#define CC const Complex&
using namespace std;
typedef long long LL;
const int N=200005,INF=1e9,mod=1e9+7;
const long double pi=acos(-1);
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        #define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=Fout)++=ch))
        char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[15];
    public:
        inline FileInputOutput() { Ftop=Fout; Fend=Fout+S; }
        Tp inline void read(T& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        Tp inline void write(T x)
        {
            RI ptop=0; while (pt[++ptop]=x%10,x/=10);
            while (ptop) pc(pt[ptop--]+48); pc(' ');
        }
        inline void flush(void)
        {
            fwrite(Fout,1,Ftop-Fout,stdout);
        }
        #undef tc
        #undef pc
}F;
struct Complex
{
    long double x,y;
    inline Complex(const long double& X=0,const long double& Y=0)
    {
        x=X; y=Y;
    }
    friend inline Complex operator + (CC A,CC B)
    {
        return Complex(A.x+B.x,A.y+B.y);
    }
    friend inline Complex operator - (CC A,CC B)
    {
        return Complex(A.x-B.x,A.y-B.y);
    }
    friend inline Complex operator * (CC A,CC B)
    {
        return Complex(A.x*B.x-A.y*B.y,A.x*B.y+A.y*B.x);
    }
    inline void operator /= (const long double& p)
    {
        x/=p; y/=p;
    }
}A[N<<2]; int a[N<<2],ans[N<<2],fact[N],inv[N];
struct edge
{
    int to,nxt;
}e[N<<1]; int n,head[N],cnt,x,y,dis[N],lim;
class FFT_Solver
{
    private:
        static const int S=ceil(sqrt(mod)),SS=1LL*S*S%mod;
        int rev[N<<2],p;
    public:
        inline void init(CI n)
        {
            for (lim=1,p=0;lim<=n;lim<<=1,++p);
            for (RI i=0;i<lim;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<p-1);
        }
        inline void FFT(Complex *f,CI opt)
        {
            RI i; for (i=0;i<lim;++i) if (i<rev[i]) swap(f[i],f[rev[i]]);
            for (i=1;i<lim;i<<=1)
            {
                Complex D(cos(pi/i),sin(pi/i)*opt);
                for (RI j=0;j<lim;j+=(i<<1))
                {
                    Complex W(1,0); for (RI k=0;k<i;++k,W=W*D)
                    {
                        Complex x=f[j+k],y=f[i+j+k]*W;
                        f[j+k]=x+y; f[i+j+k]=x-y;
                    }
                }
            }
            if (!~opt) for (i=0;i<lim;++i) f[i]/=lim;
        }
        inline void MTT(int *TA,int *TB,int *TC,CI n)
        {
            static Complex A[N<<2],B[N<<2],C[N<<2],D[N<<2],E[N<<2],F[N<<2],G[N<<2],H[N<<2];
            RI i; for (init(n<<1),i=0;i<n;++i)
            A[i]=Complex(TA[i]/S),B[i]=Complex(TA[i]%S),C[i]=Complex(TB[i]/S),D[i]=Complex(TB[i]%S);
            for (FFT(A,1),FFT(B,1),FFT(C,1),FFT(D,1),i=0;i<lim;++i)
            E[i]=A[i]*C[i],F[i]=B[i]*C[i],G[i]=A[i]*D[i],H[i]=B[i]*D[i];
            for (FFT(E,-1),FFT(F,-1),FFT(G,-1),FFT(H,-1),i=0;i<lim;++i)
            TC[i]=(((LL)(E[i].x+0.5)%mod)*SS)%mod,(TC[i]+=(((LL)(F[i].x+0.5)%mod)*S)%mod)%=mod,
            (TC[i]+=(((LL)(G[i].x+0.5)%mod)*S)%mod)%=mod,(TC[i]+=(LL)(H[i].x+0.5)%mod)%=mod;
        }
}P;
#define to e[i].to
class Point_Divide_Solver
{
    private:
        int size[N],mx[N],num[N],rt,ats,mdp; bool vis[N];
        inline void maxer(int& x,CI y)
        {
            if (y>x) x=y;
        }
        inline void getrt(CI now=1,CI fa=0)
        {
            size[now]=1; mx[now]=0; for (RI i=head[now];i;i=e[i].nxt)
            if (to!=fa&&!vis[to]) getrt(to,now),size[now]+=size[to],maxer(mx[now],size[to]);
            if (maxer(mx[now],ats-size[now]),mx[now]<mx[rt]) rt=now;
        }
        inline void travel(CI now,CI fa=0,CI dep=0)
        {
            maxer(mdp,dep); ++num[dep]; for (RI i=head[now];i;i=e[i].nxt)
            if (to!=fa&&!vis[to]) travel(to,now,dep+1);
        }
        inline void calc(CI opt)
        {
            RI i; for (P.init(mdp<<1),i=0;i<=mdp;++i) A[i]=Complex(num[i],0);
            for (i=mdp+1;i<lim;++i) A[i]=Complex();
            for (P.FFT(A,1),i=0;i<lim;++i) A[i]=A[i]*A[i];
            for (P.FFT(A,-1),lim=min(n-1,mdp<<1),i=0;i<=lim;++i)
            dis[i]+=(LL)(A[i].x+0.5)%mod*opt,(dis[i]+=mod)%=mod;
        }
        inline void clear(void)
        {
            for (RI i=0;i<=mdp;++i) num[i]=0;
        }
        inline void solve(CI now)
        {
            RI i; mdp=0; travel(now); calc(1); clear(); vis[now]=1;
            for (i=head[now];i;i=e[i].nxt) if (!vis[to])
            mdp=0,travel(to,now,1),calc(-1),clear();
            for (i=head[now];i;i=e[i].nxt) if (!vis[to])
            mx[rt=0]=INF,ats=size[to],getrt(to,now),solve(rt);
        }
    public:
        inline void divide(void)
        {
            mx[rt=0]=INF; ats=n; getrt(); solve(rt);
        }
}PD;
#undef to
inline void addedge(CI x,CI y)
{
    e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
    e[++cnt]=(edge){x,head[y]}; head[y]=cnt;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void init(void)
{
    RI i; for (fact[0]=i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;
    for (inv[n]=quick_pow(fact[n]),i=n-1;~i;--i) inv[i]=1LL*inv[i+1]*(i+1)%mod;
    for (i=0;i<n;++i) a[i]=1LL*fact[n-i-1]*dis[i]%mod;
    //for (i=0;i<n;++i) printf("%d ",a[i]); putchar('\n');
    //for (i=0;i<n;++i) printf("%d ",inv[i]); putchar('\n');
}
signed main() 
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    RI i; for (F.read(n),i=1;i<n;++i) F.read(x),F.read(y),addedge(x,y);
    for (PD.divide(),init(),P.MTT(a,inv,ans,n),i=0;i<n;++i)
    ans[n-i-1]=1LL*ans[n-i-1]*inv[n-1]%mod*fact[n-i-1]%mod;
    for (i=0;i<n;++i) F.write(ans[n-i-1]); return F.flush(),0;
}

おすすめ

転載: www.cnblogs.com/cjjsb/p/11285742.html