JZOJ5233【GDOI模拟】概率博弈
来源:互联网 发布:六级英语听力软件 编辑:程序博客网 时间:2024/06/08 07:37
Description
小A和小B在玩游戏。这个游戏是这样的:
有一棵n个点的以1为根的有根树,叶子有权值。假设有m个叶子,那么树上每个叶子的权值序列就是一个1->m 的排列。
一开始在1号点有一颗棋子。两人轮流将这颗棋子移向其当前位置的一个儿子。假如棋子到达叶子,游戏结束,最终获得的权值为所在叶子对应权值。
小A希望最后的权值尽量大,小B希望尽量小。小A是先手。
在玩了很多局游戏后,小B对其中绝大多数局游戏的结果不满意,他觉得是小A对叶子权值做了手脚。于是他一怒之下,决定将叶子的权值随机排列。现在小B想知道,假如叶子的权值是随机排列的(即叶子权值的每种排列都以等概率出现),那么游戏期望的结果是多少?
请输出答案乘上m! 对10^9+7取模的结果,显然这是一个整数。
Solution
这题有一个很套路的想法,就是我们考虑最后答案大于等于k的方案数,然后用k的方案数-k+1的方案数就是等于k的方案数。
那么大于等于k的方案数的讨论也有一个很套路的想法,就是对于所有大于等于k的权值设为1,其它设为0,然后向上合并,如果最后在根节点能合并出1,那么这种01染色方案就合法,然后再给0和1表上号就好了(0的个数的阶乘和1的个数的阶乘)
那么我们就设f[i][j][0,1]表示在第i个点,以它为根的子树的叶子节点填了j个0,当前这个点的颜色为0或1。
然后我们分层数来考虑,对于奇数层(从0层开始),那么它的儿子数有一个0,当前颜色就是0的,那么我们就用总方案-全都是1的个数来求,当前要是1的话,那么就把儿子的1做个背包,枚举前面儿子的叶子然后枚举当前要合并的儿子的叶子背包一下(这样是n^2的,相当于把所有的叶子两两之间匹配一下),对于偶数层也是一样的。
最后在根节点上恰好为k的方案,然后再标号就好了。
其实还有一种求答案的方法,我们要求的期望是
那么其实在一个平面图上就相当于1P(1),2P(2),3P(3),…nP(n),上面的方法是竖着求的,那么我们考虑横着求,设
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;typedef long long ll;const int maxn=5007,mo=1e9+7;ll i,j,k,l,t,n,m;ll first[maxn*2],last[maxn*2],next[maxn*2],num,pp;ll ni[maxn],fact[maxn],ans,f[maxn][maxn][2],son[maxn];void add(int x,int y){ last[++num]=y,next[num]=first[x],first[x]=num;}ll qsm(ll x,ll y){ ll z=1; for(;y;y/=2,x=x*x%mo)if(y&1)z=x*z%mo; return z;}ll c(ll x,ll y){ return fact[x]*ni[y]%mo*ni[x-y]%mo;}void dfs(int x,int y,int z){ int i,l=0; rep(i,x){ if(last[i]!=y){ l++;dfs(last[i],x,z+1); fod(k,son[x]+son[last[i]],0){ pp=0; fo(j,0,son[last[i]]){ if(k-j<0)break; if(z%2)(pp+=f[last[i]][j][1]*f[x][k-j][1]%mo)%=mo; else(pp+=f[last[i]][j][0]*f[x][k-j][0]%mo)%=mo; } if(z%2)f[x][k][1]=pp;else f[x][k][0]=pp; if(l==1){if(z%2)f[x][k][1]+=f[last[i]][k][1];else f[x][k][0]+=f[last[i]][k][0];} } son[x]+=son[last[i]]; } } if(!l)son[x]=1,f[x][0][1]=f[x][1][0]=1; else{ fo(j,0,son[x])if(z%2)f[x][j][0]=(c(son[x],j)-f[x][j][1]+mo)%mo;else f[x][j][1]=(c(son[x],j)-f[x][j][0]+mo)%mo; }}int main(){ freopen("game.in","r",stdin); freopen("game.out","w",stdout); fact[0]=ni[0]=1;fo(i,1,5000)fact[i]=fact[i-1]*i%mo;ni[5000]=qsm(fact[5000],mo-2); fod(i,4999,1)ni[i]=ni[i+1]*(i+1)%mo; scanf("%lld",&n); fo(i,1,n-1)scanf("%lld%lld",&k,&l),add(k,l),add(l,k); dfs(1,0,0); fo(i,0,son[1]){ ans=(ans+f[1][i][1]*fact[i]%mo*fact[son[1]-i])%mo; } ans=(ans+mo)%mo; printf("%lld\n",ans);}
- JZOJ5233【GDOI模拟】概率博弈
- 【JZOJ5233】【GDOI模拟8.5】概率博弈
- JZOJ5233 【GDOI模拟8.5】概率博弈 树形dp
- GDOI 3.21 模拟总结
- 【GDOI】模拟8.1总结
- 【GDOI】模拟8.2总结
- 【GDOI】模拟8.3总结
- GDOI模拟8.1
- 【GDOI 2013模拟】屏保
- GDOI模拟 20150806
- GDOI模拟8.6总结
- GDOI模拟8.7总结
- 【GDOI 2013模拟】Processer
- GDOI模拟 蜘蛛侠
- 【GDOI 2013模拟】总结
- gdoi 8.20模拟总结
- GDOI 8.21模拟
- GDOI模拟8.21总结
- .NET Core
- GPGPU-Sim ispass2009 编译问题0
- jzoj5246. 【NOIP2017模拟8.8A组】Trip(trip) 笛卡尔数/二维偏序
- 初步了解 selinux
- CFileFind删除过期的文件夹下的所有内容
- JZOJ5233【GDOI模拟】概率博弈
- IO流——对象的序列化
- Java 高并发缓存与Guava Cache
- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- Jenkins的分布式构建及部署——节点(转)
- 概率dp(抓老鼠)
- Android 布局优化 include,merge,viewstub标签
- bzoj1875 [SDOI2009]HH去散步(矩阵)
- 十大软件测试工具