zoukankan      html  css  js  c++  java
  • 题解 「SDOI2017」硬币游戏

    题目传送门

    Description

    周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利。

    大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了。

    同学们觉得要加强趣味性,所以要找一个同学扔很多很多次硬币,其他同学记录下正反面情况。

    用 $ exttt{H} $ 表示正面朝上, 用 $ exttt{T} $ 表示反面朝上,扔很多次硬币后,会得到一个硬币序列。比如 $ exttt{HTT} $ 表示第一次正面朝上,后两次反面朝上。

    但扔到什么时候停止呢?大家提议,选出 $ n $ 个同学, 每个同学猜一个长度为 $ m $ 的序列,当某一个同学猜的序列在硬币序列中出现时,就不再扔硬币了,并且这个同学胜利。为了保证只有一个同学胜利,同学们猜的 $ n $ 个序列两两不同。

    很快,$ n $个同学猜好序列,然后进入了紧张而又刺激的扔硬币环节。你想知道,如果硬币正反面朝上的概率相同,每个同学胜利的概率是多少。

    对于 $ 10% $ 的数据,$ 1 leq n, m leq 3 $;
    对于 $ 40% $ 的数据,$ 1 leq n, m leq 18 $;
    对于另外 $ 20%$ 的数据,$ n = 2 $;
    对于 $ 100% $ 的数据,$ 1 leq n, m leq 300 $。

    Solution

    考虑使用概率生成函数。

    我们设 ([x^n]G(x)) 表示在 (n) 次操作后仍未结束的概率,([x^n]F_i(x)) 表示在 (n) 次操作后第 (i) 个人获胜的概率,(a_{i,j,k}) 表示第 (i) 个人的 ([1,k]) 与第 (j) 个人的 ([m-k+1,m]) 是否相同。

    那我们可以得到:

    [G(x)+sum_{i=1}^{n} F_i(x)=1+x·G(x) ]

    [G(x)(frac{1}{2})^mx^m=sum_{j=1}^{n}sum_{k=1}^{m}a_{i,j,k}(frac{1}{2})^{m-k}x^{m-k}F_j(x) ]

    因为你最后只需要求出 (F_i(1)) ,所以可以把 (x) 都当成 (1) ,然后第一个式子就变为了:

    [sum_{i=1}^{n} F_i(1)=1 ]

    (似乎很显然的不需要第一个式子)

    然后你就有 (n+1) 个方程,可以直接高斯消元了。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    
    #define Int register int
    
    #define MAXN 305
    
    
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
    
    template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
    
    
    
    int n,m;
    
    char S[MAXN][MAXN];
    
    bool a[MAXN][MAXN][MAXN];
    
    double mat[MAXN][MAXN],pw2[MAXN],ans[MAXN];
    
    
    
    #define seed 1000000007
    
    #define ull unsigned long long
    
    ull pw[MAXN],pre[MAXN][MAXN],suf[MAXN][MAXN];
    
    
    
    void gauss (){
    
    	int up = n + 1;
    
    	for (Int i = 1;i <= up;++ i){
    
    		int ind = i;
    
    		for (Int j = i;j <= up;++ j) if (abs (mat[j][i]) >= 1e-7){ind = j;break;}
    
    		if (ind ^ i) swap (mat[i],mat[ind]);
    
    		for (Int j = i + 1;j <= up;++ j){
    
    			double det = mat[j][i] / mat[i][i];
    
    			for (Int k = i;k <= up + 1;++ k) mat[j][k] -= mat[i][k] * det;
    
    		}
    
    	}
    
    	for (Int i = up;i >= 0;-- i){
    
    		for (Int j = i + 1;j <= up;++ j) mat[i][up + 1] -= mat[i][j] * ans[j];
    
    		ans[i] = mat[i][up + 1] / mat[i][i];
    
    	}
    
    }
    
    
    
    signed main (){
    
    	read (n,m),pw[0] = pw2[0] = 1;
    
    	for (Int i = 1;i <= m;++ i) pw[i] = pw[i - 1] * seed,pw2[i] = pw2[i - 1] * 2;
    
    	for (Int i = 1;i <= n;++ i) scanf ("%s",S[i] + 1);
    
    	for (Int i = 1;i <= n;++ i){
    
    		for (Int j = 1;j <= m;++ j) pre[i][j] = pre[i][j - 1] * seed + (S[i][j] == 'T');
    
    		for (Int j = m;j >= 1;-- j) suf[i][j] = suf[i][j + 1] + (S[i][j] == 'T') * pw[m - j];
    
    	}
    
    	for (Int i = 1;i <= n;++ i) 
    
    		for (Int j = 1;j <= n;++ j)
    
    			for (Int k = 1;k <= m;++ k)
    
    				a[i][j][k] = (pre[i][k] == suf[j][m - k + 1]);
    
    	for (Int i = 1;i <= n;++ i){
    
    		for (Int j = 1;j <= n;++ j)
    
    			for (Int k = 1;k <= m;++ k)
    
    				if (a[i][j][k]) mat[i][j] += pw2[k];
    
    		mat[i][n + 1] = -1;
    
    	}
    
    	for (Int i = 1;i <= n;++ i) mat[n + 1][i] = 1;mat[n + 1][n + 2] = 1;
    
    	gauss ();for (Int i = 1;i <= n;++ i) printf ("%.6f
    ",ans[i]);
    
    	return 0;
    
    }
    
  • 相关阅读:
    [NOIP2017]宝藏 子集DP
    [NOI2017]蔬菜 贪心
    hihoCoder#1698 : 假期计划 组合数
    KNIGHTS
    动态图连通性(线段树分治+按秩合并并查集)
    CF868F Yet Another Minimization Problem 分治决策单调性优化DP
    【POJ】【3308】Paratroopers
    【BZOJ】【3437】小P的牧场
    【BZOJ】【3156】防御准备
    【BZOJ】【1010】【HNOI2008】玩具装箱Toy
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/15126020.html
Copyright © 2011-2022 走看看