zoukankan      html  css  js  c++  java
  • stone2 [期望]

    也许更好的阅读体验

    (mathcal{Description})
    (n) 堆石子,依次编号为 (1, 2,ldots , n),其中第 (i) 堆有 (a_i) 颗石子
    你每次在仍然有石子的石子堆中等概率随机选择一堆石子,并取走其中一颗石子
    求第 (1) 堆石子被取走的时间的期望

    (nleq 5 imes 10^5,a_ileq 5 imes 10^5)

    (mathcal{Solution})
    这题其实也不难,然而也不是考虑(DP),和stone一样
    问题要求的实际就是在第(1)堆石子被取完之前,总共有多少个石子被拿走了
    显然(a_1)被拿完了,再考虑期望的线性性,由于你取走其他堆石子对当前堆没有影响,可以单独考虑每一堆石子被取了多少个

    先考虑(a_i)没有全部被取完
    假设第(i)堆石子被取走了(xleft(0leq xleq a_i-1 ight))颗石子,因为第(i)堆石子没被取完,而没有继续被取走肯定是因为第(1)堆石子被取完了
    (1)为从第一堆石子中取一颗石子,(0)为从第二堆石子中取一颗石子
    那么方案数就是有(a_1)(1)(x)(0)的长度为(a_1+x)的且最后一位是(1)的二进制串的个数
    则有(egin{pmatrix}a_1+x-1 \ xend{pmatrix})种方案数,总方案数为(2^{a_1+x}),那么概率就是(p_x=frac{egin{pmatrix}a_1+x-1\ xend{pmatrix}}{2^{a_1+x}})

    (x=a_i),这个看起来没原来那么好算了,想到这两种情况的概率加起来应该等于(1),所以这种情况的概率就是(q=1-sumlimits_{j=0}^{a_i-1}p_j)
    则我们得到(E_i=sumlimits_{j=0}^{a_i-1}j*p_j+qa_i)
    总期望就是(E=sumlimits_{i=2}^nE_i),写复杂点就是

    (E=left(sumlimits_{i=2}^nleft(sumlimits_{j=0}^{a_i-1}j*frac{egin{pmatrix}a_1+j-1 \ jend{pmatrix}}{2^{a_1+j}} ight)+a_ileft(1-sumlimits_{j=0}^{a_i-1}frac{egin{pmatrix}a_1+j-1 \ jend{pmatrix}}{2^{a_1+j}} ight) ight)+a_1)

    这个东西怎么维护呢,直接考虑(a_i)变成(a_i+1)的情况,我们考虑里面那个(sum)的变化,实际上只有枚举上界增大(1)变成了(a_i)我们直接对(a_i)的所有取值的答案都预处理出来就行了

    (mathcal{Code})

    /*******************************
    Author:Morning_Glory
    LANG:C++
    Created Time:2019年11月08日 星期五 16时20分30秒
    *******************************/
    #include <cstdio>
    #include <fstream>
    using namespace std;
    const int maxn = 1000006;
    const int lim = 1000000;
    const int h = 500000;
    const int mod = 323232323;
    //cin为我打的快读板子,详细内容可去看以前的代码,总是在这里写感觉有点影响阅读
    int n,p,ans,a;
    int fac[maxn],ifac[maxn],inv[maxn],mi[maxn],f[maxn],g[maxn];
    int C (int n,int m){	return 1ll*fac[n]*ifac[n-m]%mod*ifac[m]%mod;}
    int main()
    {
    	fac[0]=ifac[0]=mi[0]=inv[1]=1;
    	for (int i=2;i<=lim;++i)	inv[i]=(mod-1ll*mod/i*inv[mod%i]%mod);
    	for (int i=1;i<=lim;++i)	fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*inv[i]%mod,mi[i]=1ll*mi[i-1]*inv[2]%mod;
    
    	cin>>n>>a;
    	ans=a;
    
    	//枚举上界为i
    	g[0]=mi[a];
    	for (int i=1;i<=h;++i){
    		int p=1ll*C(a+i-1,i)*mi[a+i]%mod;
    		f[i]=(f[i-1]+1ll*i*p%mod)%mod;
    		g[i]=(g[i-1]+p)%mod;
    	}
    
    	//石子数为i的答案
    	for (int i=h;i>=1;--i)	f[i]=(f[i-1]+1ll*i*(mod+1-g[i-1])%mod)%mod;
    
    	for (int i=2;i<=n;++i)	cin>>a,ans=(ans+f[a])%mod;
    
    	printf("%d
    ",ans);
    	return 0;
    }
    
    

    如有哪里讲得不是很明白或是有错误,欢迎指正
    如您喜欢的话不妨点个赞收藏一下吧

  • 相关阅读:
    HDU1698(线段树入门题)
    POJ2528(离散化+线段树区间更新)
    POJ3630(Trie树)
    HDU1251(字典树)
    HDU1247(经典字典树)
    POJ2513(字典树+图的连通性判断)
    POJ1363
    UVa11624(逃离火焰问题)
    HDOJ1495(倒水BFS)
    poj3414Pots(倒水BFS)
  • 原文地址:https://www.cnblogs.com/Morning-Glory/p/11823392.html
Copyright © 2011-2022 走看看