hdu4809(树形DP)

题意:给定一棵树(n<=300),你可以给每个节点等概率地染成A,B,C三种颜色之一,对于树上的一条边,若其两个端点的颜色不一样,则断开这条边.最后对于一个特定的颜色,X为点数为奇数的联通块个数,Y是点数为偶数的联通块个数,其得分为max(0,X-Y).问最后得分的期望乘上3^n mod 1e9+7的值.

这个题还是比较难的。。难在状态的设置吧。。(数据范围一小就不会暴力了qwq

首先可以只考虑一个颜色(设该颜色为0)的贡献,然后根据对称性把答案*3就可以得到答案了。。

设d[i][j][k]为第i个节点为0,联通块数目为奇数(j=0)或者偶数(j=1),X-Y为k的方案数

g[i][k]为第i个节点为0,X-Y为k的方案数

然后直接树上暴力转移合并就可以了,复杂度O(n^3)

跑的巨慢。。差点超时qwq

 

 

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */ 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll  long long
#define eps 1e-12
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define NM 305
#define nm 605
#define pi 3.1415926535897931
const ll inf=1e9+7;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
 
 





struct edge{int t;edge*next;}e[nm],*h[NM],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
int n,_x,_y,size[NM],cnt=150;
ll d[NM][2][455],g[NM][455],_d[2][455],_g[455],ans[455],s;

void dfs(int x,int f){
    size[x]=1;
    d[x][1][cnt]=1;g[x][cnt]=2;
    link(x)if(j->t!=f){
	dfs(j->t,x);
	memcpy(_g,g[x],sizeof(_g));memcpy(_d,d[x],sizeof(_d));mem(d[x]);mem(g[x]);
	inc(_k,0,1)inc(_v,cnt-size[j->t]/2,cnt+size[j->t])if(d[j->t][_k][_v]){
	    inc(k,0,1)inc(v,cnt-size[x]/2,cnt+size[x])if(_d[k][v])
		(d[x][k^_k][v+_v-cnt]+=d[j->t][_k][_v]*_d[k][v])%=inf;
	    inc(v,cnt-size[x]/2,cnt+size[x])if(_g[v])
		(g[x][v+_v-cnt+(_k?1:-1)]+=d[j->t][_k][_v]*_g[v])%=inf;
	}
	inc(_v,cnt-size[j->t]/2,cnt+size[j->t])if(g[j->t][_v]){
	    inc(k,0,1)inc(v,cnt-size[x]/2,cnt+size[x])if(_d[k][v])
		(d[x][k][v+_v-cnt]+=g[j->t][_v]*_d[k][v])%=inf;
	    inc(v,cnt-size[x]/2,cnt+size[x])if(_g[v])
		(g[x][v+_v-cnt]+=g[j->t][_v]*_g[v])%=inf;
	}
	size[x]+=size[j->t];
    }
}


int main(){
    while(~scanf("%d",&n)){
	mem(e);mem(h);o=e;s=0;mem(ans);mem(d);mem(g);
	inc(i,2,n){_x=read();_y=read();add(_x,_y);add(_y,_x);}
	dfs(1,0);
	inc(v,cnt-n/2,cnt+n)(ans[v+1]+=d[1][1][v])%=inf;
	inc(v,cnt-n/2,cnt+n)(ans[v-1]+=d[1][0][v])%=inf;
	inc(v,cnt-n/2,cnt+n)(ans[v]+=g[1][v])%=inf;
	inc(v,cnt+1,cnt+n)(s+=ans[v]*(v-cnt))%=inf;
	printf("%lld\n",s*3%inf);
    }
    return 0;
}

 

 

 

Cirno’s Present

Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 573    Accepted Submission(s): 180


 

Problem Description

One day, three fairies, Sunny, Luna and Star visited Cirno’s house. Cirno was very happy, so she decided to give a present to them.
Cirno’s present was a tree with N nodes. Each node of the tree has an equal possibility to be owned by one of Sunny, Luna or Star. After having decided every node’s owner, Cirno cut the edges that connect different owner’s nodes, after which each of the three fairies got some connected component of nodes (possibly none).
Then each of the three fairies had to spend some magical energy repairing the components she got. Suppose she had X components containing odd number of nodes and Y components containing even number of nodes, the magical energy she would spend equals max(0, X - Y ).
Cirno would compensate for the energy they spent with some food, so she asked you the expectation of the total energy the three fairies would spend, and your task is to find out the answer.
To make it simpler, as it’s easy to prove the multiplication of the expectation and the Nth power of three makes an integer, your task is to find the remainder of the multiplication divided by 109 + 7.

 

 

Input

There are several test cases, please process till EOF.
Each test case starts with a line containing one integer N (1 <= N <= 300). Then follows N - 1 lines, each contains two integers u and v (1 <= u, v <= N), representing an edge between node u and node v.

 

 

Output

For each test case, print the remainder of the product of the expected energy cost and the N-th power of three (actually, the remainder divided by 109 + 7) in a line.

 

 

Sample Input

 

1 2 1 2 3 2 1 1 3

 

 

Sample Output

 

3 12 51

 

 

Source

2013ACM/ICPC亚洲区南京站现场赛——题目重现

 

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

 

 

Statistic | Submit | Discuss | Note

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值