版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qkoqhh/article/details/83188031
这个很显然需要用到green博弈的结论,然后接下来就是确定树的形态了。。
设d[i][j]为大小为i的二叉树,sg值为j的方案
然后从枚举左子树大小,再把2棵子树对应的sg的情况合并一下即可。。复杂度O(n^4)。。好像比较危险。 。不过经过多次求和之后有1/10的常数,所以实际跑起来挺快的。。
n棵子树sg值的合并和上面同理。。
思路是很清晰的。。然而因为精度问题调了半天。。主要是方案数太大存不下。。所以用double可以勉强存,然而再后面合并n棵子树的时候又会炸,所以在算出方案数之后再转化为概率再计算。。
还是比较恶心。。写高精估计又要T。。
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ 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>
#include<bitset>
#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) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid ((x+y)>>1)
#define NM 205
#define nm 2005
#define pi 3.1415926535897931
const int inf=998244353;
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;
}
int n,m,a[NM];
double d[NM][NM],f[NM],ans[NM],size[NM];
int main(){
n=100;d[1][0]=d[0][0]=1;m=128;
size[1]=size[0]=1;
inc(i,2,n)inc(j,0,i-1)size[i]+=size[j]*size[i-j-1];
inc(i,2,n){
inc(j,1,m)d[i][j]=d[i-1][j-1]*2;
inc(j,1,i-2){
inc(k,0,j-1)inc(v,0,i-j-2)d[i][(k+1)^(v+1)]+=d[j][k]*d[i-j-1][v];
}
}
//inc(i,2,5){inc(j,0,i-1)printf("%d ",d[i][j]);putchar('\n');}
inc(i,1,n)inc(j,0,m)d[i][j]/=size[i];
n=read();
inc(i,1,n)a[i]=read();
inc(i,0,m)ans[i]=d[a[1]][i];
inc(i,2,n){
mem(f);
inc(j,0,m)inc(k,0,a[i])f[j^k]+=ans[j]*d[a[i]][k];
inc(j,0,m)ans[j]=f[j];
}
printf("%.6lf\n",1-ans[0]);
return 0;
}
2688: Green Hackenbush
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 92 Solved: 43
[Submit][Status][Discuss]
Description
有一个古老的游戏叫做Green Hackenbush,游戏是这样进行的:两个人轮流在一棵树上删边,每次删边后不与根联通的子树直接被ignore,不能删边的游戏者输。Alice和Bob也在玩这个游戏,不过他们面对的是n棵树,第i棵树是含有a[i]个节点的二叉树。先手的Alice想知道自己有多大的概率获胜(假设我们的Alice和Bob同学都是无限聪明的)。
Input
第一行一个数n。
接下来每行一个数a[i]。
Output
一个保留6位小数的实数ans。
Sample Input
1
2
Sample Output
1.000000
HINT
对于100%的数据,n<=100,a[i]<=100