【JZOJ5233】【GDOI模拟8.5】概率博弈 树形dp+期望
题面
小A和小B在玩游戏。这个游戏是这样的:
有一棵n个点的以1为根的有根树,叶子有权值。假设有m个叶子,那么树上每个叶子的权值序列就是一个1->m 的排列。
一开始在1号点有一颗棋子。两人轮流将这颗棋子移向其当前位置的一个儿子。假如棋子到达叶子,游戏结束,最终获得的权值为所在叶子对应权值。
小A希望最后的权值尽量大,小B希望尽量小。小A是先手。
在玩了很多局游戏后,小B对其中绝大多数局游戏的结果不满意,他觉得是小A对叶子权值做了手脚。于是他一怒之下,决定将叶子的权值随机排列。现在小B想知道,假如叶子的权值是随机排列的(即叶子权值的每种排列都以等概率出现),那么游戏期望的结果是多少?
请输出答案乘上m! 对10^9+7取模的结果,显然这是一个整数。
对于100%的数据,n<=5000,保证给出的是一棵合法的树。
100
首先预处理一个dp,\(f[i][j][0/1]\)表示以第i个结点为子树,填了j个0到叶子结点中,并且结点i的值为0/1,的方案数。
这个可以用树形背包弄出来,注意奇偶性。
然后就能统计答案了。
\]
Code
#include<bits/stdc++.h>
#define ll long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const char* fin="game.in";
const char* fout="game.out";
const int inf=0x7fffffff;
int read(){
int x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
const int maxn=5007,maxm=maxn*2,mo=1000000007;
int n,fi[maxn],la[maxm],ne[maxm],tot,ans,fact[maxn];
int w[maxn],f[maxn][maxn][2],g[maxn][maxn][2];
void add_line(int a,int b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
int getw(int v,int from){
w[v]=0;
for(int k=fi[v];k;k=ne[k])
if (la[k]!=from)
w[v]+=getw(la[k],v);
return (w[v]?w[v]:w[v]=1);
}
void dfs(int v,int from,int x){
bool az=true;
for(int k=fi[v];k;k=ne[k])
if (la[k]!=from){
dfs(la[k],v,x^1);
if (az) memcpy(f[v],f[la[k]],sizeof f[v]),az=false;
else{
fo(i,0,w[v]) g[v][i][0]=0,g[v][i][1]=0;
fo(j,0,w[la[k]])
fd(i,w[v],0){
if (i+j>w[v]) continue;
if (x==0){
g[v][i+j][0]=(g[v][i+j][0]+1ll*f[v][i][0]*f[la[k]][j][1])%mo;
g[v][i+j][0]=(g[v][i+j][0]+1ll*f[v][i][1]*f[la[k]][j][0])%mo;
g[v][i+j][0]=(g[v][i+j][0]+1ll*f[v][i][0]*f[la[k]][j][0])%mo;
g[v][i+j][1]=(g[v][i+j][1]+1ll*f[v][i][1]*f[la[k]][j][1])%mo;
}else{
g[v][i+j][1]=(g[v][i+j][1]+1ll*f[v][i][0]*f[la[k]][j][1])%mo;
g[v][i+j][1]=(g[v][i+j][1]+1ll*f[v][i][1]*f[la[k]][j][0])%mo;
g[v][i+j][1]=(g[v][i+j][1]+1ll*f[v][i][1]*f[la[k]][j][1])%mo;
g[v][i+j][0]=(g[v][i+j][0]+1ll*f[v][i][0]*f[la[k]][j][0])%mo;
}
}
fo(i,0,w[v]) f[v][i][0]=g[v][i][0],f[v][i][1]=g[v][i][1];
}
}
if (az){
f[v][0][1]=1;
f[v][1][0]=1;
}
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d",&n);
if (n==1){
printf("1");
return 0;
}
fo(i,1,n-1){
int j,k;
scanf("%d%d",&j,&k);
add_line(j,k);
add_line(k,j);
}
fact[0]=1;
fo(i,1,n) fact[i]=1ll*fact[i-1]*i%mo;
getw(1,0);
dfs(1,0,1);
fo(i,0,w[1]) ans=(ans+1ll*f[1][i][1]*fact[i]%mo*fact[w[1]-i]%mo)%mo;
ans=(ans+mo)%mo;
printf("%d",ans);
return 0;
}
【JZOJ5233】【GDOI模拟8.5】概率博弈 树形dp+期望的更多相关文章
- [CF697D]Puzzles 树形dp/期望dp
Problem Puzzles 题目大意 给一棵树,dfs时随机等概率选择走子树,求期望时间戳. Solution 一个非常简单的树形dp?期望dp.推导出来转移式就非常简单了. 在经过分析以后,我们 ...
- BZOJ 3566: [SHOI2014]概率充电器 [树形DP 概率]
3566: [SHOI2014]概率充电器 题意:一棵树,每个点\(q[i]\)的概率直接充电,每条边\(p[i]\)的概率导电,电可以沿边传递使其他点间接充电.求进入充电状态的点期望个数 糖教题解传 ...
- Codeforces 123E Maze(树形DP+期望)
[题目链接] http://codeforces.com/problemset/problem/123/E [题目大意] 给出一棵,给出从每个点出发的概率和以每个点为终点的概率,求出每次按照dfs序从 ...
- BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】
题目链接 BZOJ2878 题解 除了实现起来比较长,思维难度还是挺小的 观察数据范围发现环长不超过\(20\),而我们去掉环上任何一个点就可以形成森林 于是乎我们枚举断掉的点,然后只需求出剩余每个点 ...
- CF839 C 树形DP 期望
给一颗树,求从根出发路径长度的期望是多少. 树形DP 要想清楚期望的计算 /** @Date : 2017-08-12 23:09:41 * @FileName: C.cpp * @Platform: ...
- Codeforces 804D Expected diameter of a tree(树形DP+期望)
[题目链接] http://codeforces.com/contest/804/problem/D [题目大意] 给你一个森林,每次询问给出u,v, 从u所在连通块中随机选出一个点与v所在连通块中随 ...
- BZOJ 3566: [SHOI2014]概率充电器( 树形dp )
通过一次dfs求出dp(x)表示节点x考虑了x和x的子树都没成功充电的概率, dp(x) = (1-p[x])π(1 - (1-dp[son])*P(edge(x, son)).然后再dfs一次考虑节 ...
- BZOJ3566:[SHOI2014]概率充电器(树形DP,概率期望)
Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器: “采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器, ...
- [CSP-S模拟测试]:树(树形DP+期望)
题目描述 梦游中的你来到了一棵$N$个节点的树上.你一共做了$Q$个梦,每个梦需要你从点$u$走到点$v$之后才能苏醒,由于你正在梦游,所以每到一个节点后,你会在它连出去的边中等概率地选择一条走过去, ...
随机推荐
- 【JZOJ2679】跨时代
description 钟逆时针而绕,恶物狰狞的倾巢,我谦卑安静地于城堡下的晚祷,压抑远古流窜的蛮荒暗号,而管风琴键高傲的说,那只是在徒劳.我的乐器在环绕,时代无法淘汰我霸气的皇朝. 你无法预言,因为 ...
- JUC 一 Callable
java.util.concurrent.Callable是一个泛型接口,只有一个call()方法 Callable和Runnable的区别 Callable使用call()方法,Runnable使用 ...
- cache方法用于查询缓存操作,也是连贯操作方法之一。
cache方法用于查询缓存操作,也是连贯操作方法之一. cache可以用于select.find和getField方法,以及其衍生方法,使用cache方法后,在缓存有效期之内不会再次进行数据库查询操作 ...
- limit方法也是模型类的连贯操作方法之一
limit方法也是模型类的连贯操作方法之一,主要用于指定查询和操作的数量,特别在分页查询的时候使用较多.ThinkPHP的limit方法可以兼容所有的数据库驱动类的. 限制结果数量 例如获取满足要求的 ...
- dijkstra (模板)
突然意识到以前写的都是假的dij,感谢GhostCai神犇. #include<iostream> #include<cstdio> #include<cstring&g ...
- fastjson中List和JSONArray的相互转换
https://blog.csdn.net/xiaofei__/article/details/89571320 (1)List转换为JSONArray List<T> list = ne ...
- How to ping and test for a specific port from Linux or Unix command line
Use telnet command The syntax is:telnet {host} {port}telnet www.cyberciti.biz 80telnet 192.168.2.254 ...
- Could not resolve placeholder 'CUST_INDUSTORY' in string value "${CUST_INDUSTORY}"
问题描述 项目中的资源文件中写了个properties文件,内容这样的 CUST_FROM=002 CUST_INDUSTORY=001 CUST_LEVEL=006 在springmvc配置文件中加 ...
- linux使用wget
wget is a Linux command-line utility for retrieving files from the web, via HTTP, HTTPS and FTP prot ...
- [转]WPF更换主题
如果要做到一个应用程序其基本的内容不变,但改变整个应用程序的外观可以这样做: 对于每一套外观定义一个ResourceDictionary 在应用程序中,动态加载此应用程序(或窗体)的Resource ...