zoukankan      html  css  js  c++  java
  • [DarkBZOJ2688] Green Hackenbush

    前言

    关于水了一篇博客还想再水一篇博客但是又必须想点什么理由这件事。

    题目

    DarkBZOJ

    讲解

    首先声明:这道题的二叉树左右子树独立,比如左儿子有一条链和右儿子有一条链是两种不同的树。

    所以我们就可以轻松得出 \(n\) 个点的二叉树的棵数公式:\(cat_{n}=\sum_{i=0}^{n-1} cat_{i}\times cat_{n-i-1}\)

    如果你把Catalan的各种形式背得滚瓜烂熟或者你发现了我变量的取名特点,其实你早就可以发现这就是Catalan数。

    当然你不知道也没关系,只需要知道的是这道题这玩意可以用double存下来就好。

    我们要求的当然就是每棵树的SG值的异或和大于零的概率,对于一棵树,SG值有个经典结论,可以去上一篇博客看(找到水两篇博客的理由了!)。

    然后直接令 \(f_{i,j}\) 表示 \(i\) 个点的树,SG值为 \(j\) 的概率,转移详见代码,注意单个儿子的情况。

    然后令 \(dp_{i,j}\) 表示前 \(i\) 棵树的SG值异或和为 \(j\) 的概率,最后答案就是 \(1-dp_{i,j}\)

    时间复杂度来到了玄学的 \(O(2^{14}n^2)\)

    代码

    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 305;
    int n;
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    double cat[MAXN],f[MAXN][MAXN];//i : the number of points,j : xor
    double dp[MAXN][MAXN];
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	cat[0] = cat[1] = 1; cat[2] = 2;
    	for(int i = 3;i <= 127;++ i)
    		for(int j = 0;j < i;++ j)
    			cat[i] += cat[j] * cat[i-j-1];
    	f[1][0] = 1;
    	for(int i = 2;i <= 100;++ i)
    	{
    		for(int j = 0;j <= 127;++ j) f[i][j+1] += 2.0 * f[i-1][j] * cat[i-1];
    		for(int c = 1;c < i-1;++ c) 
    			for(int j = 0;j <= 127;++ j)
    				for(int k = 0;k <= 127;++ k)
    					f[i][(j+1)^(k+1)] += cat[c] * f[c][j] * cat[i-c-1] * f[i-c-1][k];
    		for(int j = 0;j <= 127;++ j) f[i][j] /= cat[i];
    	}
    	n = Read();
    	int val = Read(); 
    	for(int i = 0;i <= 127;++ i) dp[1][i] = f[val][i];
    	for(int i = 2;i <= n;++ i)
    	{
    		val = Read();
    		for(int j = 0;j <= 127;++ j)
    			for(int k = 0;k <= 127;++ k)
    				dp[i][j^k] += dp[i-1][j] * f[val][k];
    	}
    	printf("%.6f\n",1-dp[n][0]);
    	return 0;
    }
    
  • 相关阅读:
    参数默认值
    调用外部 DLL 中的函数(1. 早绑定)
    Delphi 运行时错误信息表
    分享:PyPyODBC 0.9.2发布 纯Python实现的pyodbc替代库
    我的书单
    我的书单
    Philip Guo googler
    我的书单
    isbn2title
    我的书单
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15724352.html
Copyright © 2011-2022 走看看