• CF712E Memory and Casinos 期望,概率复习


    题目链接

    CF712E Memory and Casinos

    (Firstly),前言

    这道题是道假的黑题

    一群学弟比我先A ,我真是太弱了

    我们的思路都应该是来自于这位大佬的 czpcf

    自我认为他们的公式都推得很草率

    所以我才决定再 写一篇

    (Secondly),思路

    定义 (f(i,j)) 为从赌场(i)出发 在赌场(i)赢 在赌场(j)赢并结束的概率

    定义 (f(j + 1,k)) 为从赌场(j) + 1出发 在赌场(j) + 1赢 在赌场(k)赢并结束的概率

    定义 (g(i,j))(f)恰相反

    那么 (f(i,k)) = 直接走过去的概率(这里中间也可能转了圈 但没有过(j)) + 在中间转了圈且走过去的概率(中间的圈过了(j))

    直接走过去的概率 = (f(i,j) *f(j + 1,k))

    在中间转了圈且走过去的概率 = (f(i,j) *f(j + 1,k))*(displaystylesum^{+infty}_{p=1}w^p)

    其中(w)为在中间转一圈的概率

    重点就是 (w)怎么算

    (w) = ((1-f(j+1,k))(1-g(i,j)))

    这个式子是怎么得出的呢?

    先理解(1-f(j+1,k))

    为从赌场(j) + 1出发 在赌场(j) + 1赢 在赌场(k)赢并结束的概率

    这里 (1-f(j+1,k))

    赌场(j) + 1出发是默认的

    条件只有

    • 1:在赌场(j) + 1赢

    • 2:在赌场(k)

    两个中至少有一个不成立

    但最后(1,2)造成的结果都是从右区间返回 (不管她在([j + 1,k])转多少圈)

    (Additionally),化简

    [f(i,k) ]

    [= f(i,j) *f(j + 1,k)displaystylesum^{+infty}_{p=1}w^p ]

    [= f(i,j) *f(j + 1,k)frac{1-w^{+infty}}{1-w} ]

    [w^{+infty} = 0 ]

    [Rightarrow= frac{f(i,j) *f(j + 1,k)}{1-(1-f(j+1,k))(1-g(i,j))} ]

    这下就可以用线段树维护了

    (Eventually)(Code)

    #include <map>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define reg register int
    #define isdigit(x) ('0' <= (x)&&(x) <= '9')
    template<typename T>
    inline T Read(T Type)
    {
    	T x = 0,f = 1;
    	char a = getchar();
    	while(!isdigit(a)) {if(a == '-') f = -1;a = getchar();}
    	while(isdigit(a)) {x = (x << 1) + (x << 3) + (a ^ '0');a = getchar();}
    	return x * f;
    }
    #define fi first
    #define se second
    typedef double db;
    const int MAXN = 100010;
    db p[MAXN];
    struct node
    {
    	double g,f;
    }tree[MAXN << 2];
    inline void sum(db &f,db &g,db f1,db f2,db g1,db g2)
    {
    	f = f1 * f2 / (1 - (1 - f2) * (1 - g1));
    	g = g1 * g2 / (1 - (1 - f2) * (1 - g1));
    }
    inline void BuildTree(int k,int l,int r)
    {
    	if(l == r)
    	{
    		tree[k].f = p[l],tree[k].g = 1 - p[l];
    		return;
    	}
    	int mid = l + r >> 1;
    	BuildTree(k << 1,l,mid);
    	BuildTree(k << 1 | 1,mid + 1,r);
    	sum(tree[k].f,tree[k].g,tree[k << 1].f,tree[k << 1 | 1].f,tree[k << 1].g,tree[k << 1 | 1].g);
    }
    inline pair<db,db> query(int k,int l,int r,int L,int R)
    {
    	if(L <= l&&r <= R) return make_pair(tree[k].f,tree[k].g);
    	int mid = l + r >> 1;
    	pair<db,db> k1,k2;k1.fi = k2.fi = k1.se = k2.se = 1;
    	if(L <= mid) k1 = query(k << 1,l,mid,L,R);
    	if(mid < R) k2 = query(k << 1 | 1,mid + 1,r,L,R);
    	db T1,T2;
    	sum(T1,T2,k1.fi,k2.fi,k1.se,k2.se);
    	return make_pair(T1,T2);
    }
    inline void update(int k,int l,int r,int pos,db x)
    {
    	if(l == r)
    	{
    		tree[k].f = x,tree[k].g = 1 - x;
    		return;
    	}
    	int mid = l + r >> 1;
    	if(pos <= mid) update(k << 1,l,mid,pos,x);
    	else update(k << 1 | 1,mid + 1,r,pos,x);
    	sum(tree[k].f,tree[k].g,tree[k << 1].f,tree[k << 1 | 1].f,tree[k << 1].g,tree[k << 1 | 1].g);
    }
    int main()
    {
    	int n = Read(1),q = Read(1);
    	for(reg i = 1;i <= n;i++)
    	{
    		int a = Read(1),b = Read(1);
    		p[i] = (db)a / b;
    	}
    	BuildTree(1,1,n);
    	while(q--)
    	{
    		int sit = Read(1);
    		if(sit & 1)
    		{
    			int pos = Read(1),a = Read(1),b = Read(1);
    			update(1,1,n,pos,((db)a / b));
    		} else {
    			int l = Read(1),r = Read(1);
    			cout << query(1,1,n,l,r).fi << endl;
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    Python学习日志(三)
    Python学习日志(二)
    软件测试入门随笔——软件测试基础知识(八)
    软件测试入门随笔——软件测试基础知识(七)
    软件测试入门随笔——软件测试基础知识(六)
    fastcgi 性能初配 504 gateway time-out
    php 文件锁
    php sleep()的实时输出打印,清除ob缓冲区
    php用simplexml来操作xml
    PHP防SQL注入不要再用addslashes和mysql_real_escape_string
  • 原文地址:https://www.cnblogs.com/resftlmuttmotw/p/11719396.html
Copyright © 2020-2023  润新知