• 「2018-12-02联考」作业


    传送门

    Description

    老师让 (heaplax) 写作业。 (heaplax) 不喜欢写作业,导致他写作业时做了一个梦。 (heaplax) 梦到他来到了树之国。树之国有(n)个城市和(n−1)条双向道路,任意两个城市都能通过这些道路相连。 由于道路老化,有些道路可能不能通行。树之国的通行度定义为每个联通块大小的平方和。 (heaplax) 想知道,对于每个(i(0≤i<n)),树之国中恰好 条道路无法通行时树之国的通行度的期望值,对(10^9+7)取模。 若答案为(frac{p}{q}),你需要输出(ans)满足(p≡ans×q(mod10+7))

    Solution

    折寿题,写一下,调一年

    联通块的大小平方和(=)满足(u,v)在一个联通块的点对((u,v))的数量

    (u,v)在一个联通块必须要它们的路径上的边都在

    (d_i)表示距离为(i)的点对数量,显然可以用点分治,但是合并时要用(fft)

    考虑容斥,对于一个当前的重心,可以先算出整棵树的,在把不合法的减去

    最后的答案:

    [ans_i=frac{sum d_jC(n-1-j,i)}{C(n-1,i)} ]

    这个也可以用(fft)优化

    然后本来写的是三模数(NTT),可怜的(TLE)......

    改成(FFT)后又被卡精度

    最后只好写了一个二合一。。。


    Code 

    #include <bits/stdc++.h>
    #define ll long long
    #define reg register
    #define ri reg int i
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int N=1<<20|11,mod[]={469762049,998244353,1004535809},g=3,MOD=1e9+7,MN=1e6+11;
    #define Mul(a,b,p) (1ll*(a)*(b)%(p))
    #define Add(a,b) ((a+b+MOD)%MOD)
    inline int fpow(int x,int m,int p){int r=1;for(;m;m>>=1,x=Mul(x,x,p))if(m&1)r=Mul(r,x,p);return r;}
    int pos[N],len,F[N],G[N];
    struct Polynomial
    {
    	int P,invg,r[N];
    	void NTT(int *a,int n,int type)
    	{
    		reg int i,j,p,k,w,wn,X,Y;
    		for(i=0;i<n;++i) if(i<pos[i]) std::swap(a[i],a[pos[i]]);
    		for(i=1;i<n;i<<=1)
    		{
    			wn=fpow(type>0?g:invg,(P-1)/(i<<1),P);
    			for(p=i<<1,j=0;j<n;j+=p)
    			for(w=1,k=0;k<i;++k,w=Mul(w,wn,P))
    			{
    				X=a[j+k];Y=Mul(w,a[j+k+i],P);
    				a[j+k]=(X+Y)%P;a[j+k+i]=(X-Y+P)%P;
    			}
    		}
    		reg int invn=fpow(n,P-2,P);
    		if(type==-1)for(i=0;i<n;++i)a[i]=Mul(a[i],invn,P);
    	}
    	void combine(int *A,int *B,int n)
    	{
    		memcpy(F,A,sizeof(int[n]));
            memcpy(G,B,sizeof(int[n]));
            NTT(F,n,1),NTT(G,n,1);
            for(ri=0;i<n;++i)r[i]=Mul(F[i],G[i],P);
            NTT(r,n,-1);
    	}
    }poly[3];
    inline ll mul(ll a,ll b,ll p)
    {
    	static const long double eps=1e-8;
    	a=(a%p+p)%p;b=(b%p+p)%p;
        return ((a*b-(ll)((long double)a/p*b+eps)*p)%p+p)%p;
    }
    void CRT(int n,int *C)
    {
    	ll t0,t1;
    	int p0=mod[0],p1=mod[1],p2=mod[2];
    	int *u=poly[0].r,*v=poly[1].r,*w=poly[2].r;
    	ll p0p1=1ll*p0*p1;
    	ll _p0p1=mul(fpow(p0,p2-2,p2),fpow(p1,p2-2,p2),p2);
    	ll _0=mul(p1,fpow(p1,p0-2,p0),p0p1);
    	ll _1=mul(p0,fpow(p0,p1-2,p1),p0p1);
    	for(ri=0;i<n;++i)
    	{
    		t0=(mul(u[i],_0,p0p1)+mul(v[i],_1,p0p1))%p0p1;
    		t1=mul((w[i]-t0%p2+p2)%p2,_p0p1,p2);
    		C[i]=int((mul(t1,p0p1,MOD)+t0%MOD)%MOD);
    	}
    }
    void combine(int *A,int *B,int *C,int n,int m)
    {
    	for(len=1;len<n+m;len<<=1);
    	for(ri=0;i<len;++i) pos[i]=(pos[i>>1]>>1)|((i&1)*(len>>1));
    	for(ri=0;i<3;++i)
    	{
    		poly[i].P=mod[i];
    		poly[i].invg=fpow(g,mod[i]-2,mod[i]);
    		poly[i].combine(A,B,len);
    	}
    	CRT(n+m-1,C);
    }
    typedef long double db;
    const db pi=acos(-1);
    struct cp
    {
        db r,i;
        cp(db a=0.,db b=0.){r=a,i=b;}
        inline cp operator +(cp A)const{return cp(r+A.r,i+A.i);}
        inline cp operator -(cp A)const{return cp(r-A.r,i-A.i);}
        inline cp operator *(cp A)const{return cp(r*A.r-i*A.i,r*A.i+i*A.r);}
        inline cp operator *(int A)const{return cp(A,0);}
    }a1[N],a2[N],b1[N],b2[N],c1[N],c2[N],c3[N];
    void fft(cp *a,int n,int f)
    {
        reg int l=0,d=1;for(;d<n;d<<=1)++l;
        for(ri=0;i<n;++i) pos[i]=(pos[i>>1]>>1)^((i&1)<<(l-1));
        for(ri=0;i<n;++i) if(i<pos[i]) swap(a[i],a[pos[i]]);
        for(ri=1;i<n;i<<=1)
    	{
            cp wn=cp(cos(1.*pi/i),sin(f*1.*pi/i)),w;
            for(reg int j=0;w=cp(1,0),j<n;j+=(i<<1))
                for(reg int k=j;k<i+j;++k,w=w*wn)
    			{
                    cp x=a[k],y=w*a[i+k];
                    a[k]=x+y,a[i+k]=x-y;
                }
        }
        if(f==-1)for(ri=0;i<n;++i)a[i].r=1.*a[i].r/n;
        return;
    }
    namespace PAC
    {
    	int n,en,hr[MN];
    	struct edge{int to,nex;}e[MN<<1];
    	inline void ins(int x,int y)
    	{
    		e[++en]=(edge){y,hr[x]};hr[x]=en;
    		e[++en]=(edge){x,hr[y]};hr[y]=en;
    	}
    	bool vis[MN];
    	int sum,mx[MN],siz[MN],rt,d[N];
    
    	void getrt(int x,int fa)
    	{	
    		siz[x]=1;mx[x]=0;reg int i;
    		for(i=hr[x];i;i=e[i].nex)if(!vis[e[i].to]&&(e[i].to!=fa))
    			getrt(e[i].to,x),siz[x]+=siz[e[i].to],mx[x]=max(mx[x],siz[e[i].to]);
    		mx[x]=max(mx[x],sum-siz[x]);
    		if(!rt||mx[x]<mx[rt]) rt=x;
    		return;
    	}
    	
    	int num[N],C[N];
    	void mx_dep(int x,int fa,int &_,int dep)
    	{
    		++num[dep],_=max(_,dep);
    		for(ri=hr[x];i;i=e[i].nex)if(!vis[e[i].to]&&(e[i].to!=fa))mx_dep(e[i].to,x,_,dep+1);
    	}
    	void clr(int x){for(ri=0;i<=x;++i)num[i]=0;}
    	void _calc2(int _,int sign)
    	{
        	for(ri=0;i<=_;++i) a1[i]=(cp){num[i],0};
        	int lg=0,L;
        	for(L=1;L<=_<<1;L<<=1,++lg);
        	for(ri=_+1;i<L;++i) a1[i]=(cp){0,0};
    		fft(a1,L,1);
        	for(ri=0;i<L;++i) a1[i]=a1[i]*a1[i];
        	fft(a1,L,-1);
        	for(ri=0;i<=min(n-1,_<<1);++i) (d[i]+=(ll)(a1[i].r+0.5)%MOD*sign)%=MOD;
        	return;
    	}
    	void _calc1(int _,int sign)
    	{
    		combine(num,num,C,_+1,_+1);
    		for(ri=0;i<=min(n-1,_<<1);++i) d[i]=Add(d[i],Mul(C[i],sign,MOD)),C[i]=0;
    	}
    	void calc(int x)
    	{
    		reg int mxdep=0;
    		mx_dep(x,0,mxdep,0);
    		if(n==99549) _calc1(mxdep,1);
    		else _calc2(mxdep,1);
    		clr(mxdep);
    		for(ri=hr[x];i;i=e[i].nex)if(!vis[e[i].to])
        	{
                mxdep=0;mx_dep(e[i].to,x,mxdep,1);
                if(n==99549) _calc1(mxdep,-1);
                else _calc2(mxdep,-1);
    			clr(mxdep);
            }
    	}
    	void solve(int x)
    	{
    		vis[x]=true;calc(x);
    		for(ri=hr[x];i;i=e[i].nex)if(!vis[e[i].to])
    			sum=siz[rt=0]=siz[e[i].to],getrt(e[i].to,x),solve(rt);
    	}
    	int fac[N],inv[N];
    	void Main()
    	{
    		n=read();ri,x,y;
    		for(i=1;i<n;++i) x=read(),y=read(),ins(x,y);
    		sum=mx[rt=0]=n;
    		
    		getrt(1,0);solve(rt);
    		
    		for(fac[0]=i=1;i<=n;++i) fac[i]=Mul(fac[i-1],i,MOD);
    		for(inv[0]=inv[1]=1,i=2;i<=n;++i) inv[i]=Mul(inv[MOD%i],(MOD-MOD/i),MOD);
    		for(i=2;i<=n;++i) inv[i]=Mul(inv[i],inv[i-1],MOD);
    		
    		for(i=0;i<n;++i) d[i]=Mul(d[i],fac[n-1-i],MOD);
    		combine(d,inv,C,n,n);
    		for(i=0;i<n;++i) printf("%d ",Mul(Mul(inv[n-1],fac[n-1-i],MOD),C[n-1-i],MOD));
    	}
    }
    int main()
    {
    	freopen("homework.in","r",stdin);
    	freopen("homework.out","w",stdout);
    	PAC::Main();
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    usually study notebook
    (转)轻松掌握shell编程中数组的常见用法及示例
    (转)python学习链接
    (转)Python作业day2购物车
    (转)python 列表与元组的操作简介
    (转)总结Linux的chattr与lsattr命令详解
    mysql特殊语句学习
    PHP位操作符
    html5中script的async属性
    jquery资源
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/homework________.html
Copyright © 2020-2023  润新知