zoukankan      html  css  js  c++  java
  • 西行妖

    题目

    在幻想乡白玉楼有一棵终年不开花的樱树叫西行妖,西行寺幽幽子曾经为了让它开花而大量收集春度,然后被城管教训了一顿...
    现在,幽幽子得到城管的允许,收集了S点春度,让西行妖重新开花。
    西行妖可以被看成是一棵有n个节点的树,每个叶子节点被分配了1点春度就能开花(幽幽子不会无意义地使用她的春度,于是最多只会给同一个叶子节点分配1点春度),对于非叶子节点i,如果它有至少有1个儿子开花,那么节点i能开花。
    据说,西行妖的花开满之时,幽幽子会复活。但是城管只给了S点春度(S≤20),所以幽幽子这次是抱着娱乐的心态种树的。
    如果西行妖有至少m个节点开花,那么幽幽子认为它是美丽的。现在幽幽子想知道,有多少种方案,使西行妖是美丽的(答案对10^9+7取模)。
    注意:幽幽子不一定会把S点春度都分配完。

    分析

    (f_{i,j,k})表示,第(i)个叶子节点分配了第(j)个春点,共开了(k)朵花的方案数。
    那么转移为$$f_{i,j,k}=sum_{l=1}^{i-1}f_{l,j-1,k-deep(i)+deep(lca(i,l))}(为了让k不被算多,将叶子节点按dfn序排序))$$
    这样的时间复杂度是(O(n^{3}S))的,显然会超时。

    然后发现,事实上很多的(f_{l,j-1,k-deep(i)+deep(lca(i,l))})会为0,对答案没贡献。所以我们想办法把这些多余的状态删掉。
    我们可以从前面转移到后面,当发现当前面的(f_{i,j,k})为0的时候,就不转移。

    [f_{l,j+1,k+deep(l)-deep(lca(i,l))}=f_{l,j+1,k+deep(l)-deep(lca(i,l))}+f_{i,j,k} ]

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=1005;
    using namespace std;
    int fa[N],n,m,s,ans,deep[N],g[N][15],f[N][21][N],a[N][N],d[N],tot,lca[N][N];
    int dg(int x)
    {
    	if(!a[x][0])
    	{
    		d[++tot]=x;
    		return 0;
    	}
    	for(int i=1;i<=a[x][0];i++)
    	{
    		deep[a[x][i]]=deep[x]+1;
    		dg(a[x][i]);
    	}
    }
    int lca1(int x,int y)
    {
        int l;
        if(deep[x]<=deep[y])
        {
            l=x;
            x=y;
            y=l;
        }
        int p=0;
        for(int i=log2(n);i>=0;i--)
        {
            if(deep[g[x][i]]>=deep[y])
            {
                x=g[x][i];
            }
        }
        for(int i=log2(n);i>=0;i--)
        {
            if(g[x][i]!=g[y][i])
            {
                x=g[x][i];
                y=g[y][i];
            }
        }
        x=g[x][0];
        return x;
    }
    int main()
    {
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&s);
    	for(int i=2;i<=n;i++)
    	{
    		scanf("%d",&fa[i]);
    		g[i][0]=fa[i];
    		a[fa[i]][++a[fa[i]][0]]=i;
    	}
    	deep[1]=1;
    	dg(1);
    	for(int j=1;j<=log2(n);j++)
    		for(int i=1;i<=n;i++)
    		{
    			g[i][j]=g[g[i][j-1]][j-1];		
    		}
    	f[0][0][0]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    		{
    			lca[i][j]=lca1(i,j);
    		}
    	for(int i=0;i<=tot-1;i++)
    	{
    		for(int j=0;j<=min(s-1,i);j++)
    			for(int k=0;k<=n;k++)
    			{
    				if(f[d[i]][j][k])
    				{
    					for(int l=i+1;l<=tot;l++)
    					{
    						(f[d[l]][j+1][k+deep[d[l]]-deep[lca[d[l]][d[i]]]]+=f[d[i]][j][k])%=mo;
    					}
    				}
    			}
    	}
    	for(int i=1;i<=tot;i++)
    		for(int j=1;j<=s;j++)
    			for(int k=m;k<=n;k++)
    				(ans+=f[d[i]][j][k])%=mo;
    	printf("%d",ans);
    }
    
    
  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/chen1352/p/9043439.html
Copyright © 2011-2022 走看看