• 简单题 解题报告


    简单题

    给一颗(n(le 80))节点的树,开始所有节点都是白色,每个时间随机染黑一条链,求把整棵树染黑的期望时间,对(998244353)取模


    考虑(min-max)容斥

    某集合(S)最后一个点出现的期望时间为(max S),第一个点出现的期望时间是(min S),则有

    [max(S)=sum_{varnothing ot=Tsubseteq S}(-1)^{T-1}min (T) ]

    考虑求出(min T)

    一个显然的暴力是枚举所有(T),然后枚举所有染色方案,求出不经过这(T)的染色方案的概率(p)

    那么(min (T)=sumlimits_{i= 0}^{infty}p^i=frac{1}{1-p})

    于是可以(dp)染色方案数目,求出概率

    (dp_{i,j,k})表示(i)子树有(j)个点到(i)的路径上没有白点且共有(k)条路径没有白点的方案数,并把容斥系数也带上

    转移的时候枚举每一维,然后拼一拼,第二维压进去是给第三维转移用的,至于复杂度,不是很清楚呢...


    Code:

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    template <class T>
    void read(T &x)
    {
    	x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    const int mod=998244353;
    const int N=85;
    inline void add(int &a,int b){a=a+b>=mod?a+b-mod:a+b;}
    #define mul(a,b) (1ll*(a)*(b)%mod)
    int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
    int head[N],Next[N<<1],to[N<<1],cnt;
    void addedge(int u,int v)
    {
    	to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int dp[N][N][N*N/2],f[N][N*N/2],siz[N],n,ans;
    void dfs(int now,int fa)
    {
    	dp[now][0][0]=mod-1;
    	dp[now][1][1]=1;
    	siz[now]=1;
    	for(int v,p=head[now];p;p=Next[p])
    		if((v=to[p])!=fa)
    		{
    			dfs(v,now);
    			for(int i=0;i<=siz[now];i++)
    				for(int k=i*(i+1)/2;k<=siz[now]*(siz[now]+1)/2;k++)
    					if(dp[now][i][k])
    						for(int j=0;j<=siz[v];j++)
    							for(int l=j*(j+1)/2;l<=siz[v]*(siz[v]+1)/2;l++)
    								add(f[i?i+j:0][k+l+i*j],mul(dp[now][i][k],dp[v][j][l]));
                siz[now]+=siz[v];
                for(int i=0;i<=siz[now];i++)
                    for(int k=0;k<=siz[now]*(siz[now]+1)/2;k++)
                        dp[now][i][k]=f[i][k],f[i][k]=0;
    		}
    }
    int main()
    {
        freopen("jiandanti.in","r",stdin);
        freopen("jiandanti.out","w",stdout);
        read(n);
        for(int u,v,i=1;i<n;i++) read(u),read(v),addedge(u,v),addedge(v,u);
        dfs(1,0);
    	int m=n*(n+1)/2;
    	for(int i=0;i<=m;i++)
    	{
    		int t=0;
    		for(int j=0;j<=n;j++) add(t,dp[1][j][i]);
    		add(ans,mul(mod-1,mul(t,mul(m,qp(m-i,mod-2)))));
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    2019.3.28

  • 相关阅读:
    eclipse上运行spark程序
    Java实现高斯模糊算法处理图像
    Hadoop环境共享
    P1182 数列分段`Section II`
    NOIP2015题解
    镜面上的迷失之链 —— 二分判定性问题
    网络最大流
    [IOI2008]Island
    历史的进程——单调队列
    快速幂
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10617101.html
Copyright © 2020-2023  润新知