• 题解:Luogu P4516 [JSOI2018]潜入行动


    题面

    一道 simple 的树形 DP

    设状态 (f(i,j,0/1,0/1)) 表示在节点 (i) 作为根节点的子树内 该节点用了 (j) 个监听设备 该节点不放/放 该节点在该子树内被不被监听/被监听 的方案数

    [egin{cases} f(u,0,0,0) = 0\ f(u,1,1,0) = 0\ f(u,i+j,0,0) = displaystyle{sum_{(u,v)in T} f(u,i,0,0) imes f(v,j,0,1)} \ f(u,i+j,0,1) = displaystyle{sum_{(u,v)in T} f(u,i,0,1) imes (f(v,j,1,1)+f(v,j,0,1))\ + f(u,i,0,0) imes f(v,j,1,1)}\ \ f(u,i+j,1,0) = displaystyle{sum_{(u,v)in T} f(u,i,1,0) imes(f(v,j,0,1)+f(v,j,0,0))}\ f(u,i+j,1,1) = displaystyle{sum_{(u,v)in T} f(u,i,1,1) imes(f(v,j,0,0)+f(v,j,0,1)+f(v,j,1,0)\ +f(v,j,1,1)) + f(u,i,1,0) imes(f(v,j,1,1)+f(v,j,1,0))}\ end{cases} ]

    树形 DP 时,每次只要算 min(size[u]+size[v],k) 的情况就行了,我的代码复杂度是 (mathcal{O}(nlog n imes k))

    Code(C++):

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(int i=(s);i<=(t);++i)
    #define form(i,s,t) for(int i=(s);i>=(t);--i)
    using namespace std;
    typedef long long ll;
    const int N = 1e5+3,M = 103,Mod = 1e9+7;
    template<typename T> inline T mod(T A) {return A>Mod?A%=Mod:A;}
    template<typename T> inline T Dif(T A) {return A>Mod?A-=Mod:A;}
    struct List {
    	int dir,nxt;
    }E[N<<1];
    int G[N],cnt;
    inline void Add(int u,int v) {
    	E[++cnt].dir = v,E[cnt].nxt = G[u],G[u] = cnt;
    }
    int n,k,sz[N],f[N][M][2][2],g[2][2][M];
    void dfs(int u,int fa) {
    	sz[u] = 1,f[u][0][0][0] = f[u][1][1][0] = 1;
    	for(int s=G[u];s;s=E[s].nxt) {
    		int v = E[s].dir;
    		if(v == fa) continue ;
    		dfs(v,u);
    		forn(i,0,min(k,sz[u]+sz[v])) g[0][0][i] = g[0][1][i] = g[1][0][i] = g[1][1][i] = 0;
    		forn(i,0,min(k,sz[u])) forn(j,0,min(k-i,sz[v])) {
    			g[0][0][i+j] = Dif((ll)g[0][0][i+j]+mod((ll)f[u][i][0][0]*f[v][j][0][1]));
    			g[0][1][i+j] = Dif((ll)g[0][1][i+j]+Dif(mod((ll)f[u][i][0][1]*Dif(f[v][j][1][1]+f[v][j][0][1]))+
    								mod((ll)f[u][i][0][0]*f[v][j][1][1])));
    			g[1][0][i+j] = Dif((ll)g[1][0][i+j]+mod((ll)f[u][i][1][0]*Dif(f[v][j][0][1]+f[v][j][0][0])));
    			g[1][1][i+j] = Dif((ll)g[1][1][i+j]+Dif(mod((ll)f[u][i][1][1]*Dif(Dif(f[v][j][0][1]+f[v][j][1][1])+																                        
                                                                                              Dif(f[v][j][1][0]+f[v][j][0][0])))+
    								mod((ll)f[u][i][1][0]*Dif(f[v][j][1][1]+f[v][j][1][0]))));
    		}
    		sz[u] += sz[v];
    		forn(i,0,min(k,sz[u])) f[u][i][0][0] = g[0][0][i],f[u][i][0][1] = g[0][1][i],
    				       f[u][i][1][0] = g[1][0][i],f[u][i][1][1] = g[1][1][i];
    	}
    }
    int main() {
    	scanf("%d%d",&n,&k);
    	int u,v;
    	forn(i,1,n-1) scanf("%d%d",&u,&v),Add(u,v),Add(v,u);
    	dfs(1,0);
    	printf("%lld
    ",Dif((ll)f[1][k][1][1]+f[1][k][0][1]));
    	return 0;
    }
    
  • 相关阅读:
    【转】三层架构,MVC, ASP.net MVC的区别
    code-Behind
    从输入 URL 到页面加载完成的过程中都发生了什么事情?
    javascript杂谈
    网页设计中透明效果的使用技巧
    phpstorm+Xdebug断点调试PHP
    MySql IFNULL 联表查询出来的null 如何赋值
    php读取目录下的文件
    CI框架程序--本地调试之后部署新浪SAE
    各个手机APP客户端内置浏览器useragent
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/14083705.html
Copyright © 2020-2023  润新知