• 「ZJOI2019」开关


    传送门

    Description

    有一些一开始全都是关的开关,每次随机选择一个(每个开关概率不同)开关并改变它的状态,问达到目标状态的期望步数

    Solution 

    (P=sum_{i=1}^{n}p_i)

    求出(k)步达到目标状态的概率的(EGF)

    [F(x)=prod_{i=1}^nfrac{e^{frac{p_ix}{P}}+(-1)^{s_i}e^{-frac{p_ix}{P}}}{2} ]

    再求出(k)步回到原来的状态的概率的(EGF)

    [G(x)=prod_{i=1}^nfrac{e^{frac{p_ix}{P}}+e^{-frac{p_ix}{P}}}{2} ]

    对于上述函数,可以用背包求出(F(x)=sum_{i=-P}^P a_ie^{frac{ix}{P}})中的系数(a_i)(G(x))的系数为(b_i)

    (k)步到达且不多次到达目标状态的概率的(EGF)(H(x))

    (H(x),F(x),G(x))对应的(OGF)分别是(h(x),f(x),g(x))

    那么可知(g(x)h(x)=f(x))

    如何实现(EGF)(OGF)的转化?

    [egin{equation} egin{split} F(x)&=sum_{i=-P}^Pa_ie^{frac{ix}{P}} \&=sum_{i=-P}^P a_isum_{jgeq0}frac{(frac{ix}{P})^j}{j!} end{split} end{equation} ]

    所以

    [f(x)=sum_{i=-P}^Pfrac{a_i}{1-frac{ix}{P}} ]

    发现我们要求的答案就是(h'(1))

    [h'(1)=(frac{f(1)}{g(1)})'=frac{f'(1)g(1)-f(1)g'(1)}{g^2(1)} ]

    计算时,把(f,g)同乘上(prod_{i=_P}^P(1-frac{ix}{P}))。下述(f,g)均已乘上左式。

    计算得到:

    [f(1)=a_Pprod_{i=-P}^{P-1}(1-frac{i}{P}) \g(1)=b_Pprod_{i=-P}^{P-1}(1-frac{i}{P}) ]

    求导得到:

    [f'(1)=sum_ia_isum_{j eq i}-frac{j}{P}prod_{k eq i,k eq j}(1-frac{k}{P})\g'(1)=sum_ib_isum_{j eq i}-frac{j}{P}prod_{k eq i,k eq j}(1-frac{k}{P}) ]

    整理得到:

    [f'(1)=-(sum_{i eq P}frac{a_i+a_Pcdot frac{i}{P}}{1-frac{i}{P}})(prod_{i eq P} (1-frac{i}{P})) \ g'(1)=-(sum_{i eq P}frac{b_i+b_Pcdot frac{i}{P}}{1-frac{i}{P}})(prod_{i eq P} (1-frac{i}{P})) ]

    直接代入(a_P=b_P=2^{-n}),最后答案为(2^nsum_{i eq P}frac{b_i-a_i}{1-frac{i}{P}})


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    #define reg register
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MX=5e4+5,M=998244353,inv2=(M+1)>>1;
    int Mul(int x,int y){return (1ll*x*y)%M;}
    int Add(int x,int y){return (x+y)%M;}
    int fpow(int x,int y=M-2){int r=1;for(;y;y>>=1,x=Mul(x,x))if(y&1)r=Mul(r,x);return r;}
    int n,a[MX<<1],b[MX<<1],s[105],p[105],P=0;
    int f[2][MX<<1],g[2][MX<<1];
    int _(int x){return x+P;}
    int main()
    {
    	n=read();register int i,j,k;
    	for(i=1;i<=n;++i) s[i]=read();
    	for(i=1;i<=n;++i) p[i]=read(),P+=p[i];
    	f[0][P]=g[0][P]=1;
    	for(k=0,i=1;i<=n;k+=p[i],++i)
    	{
    		memset(f[i&1],0,sizeof f[i&1]);
    		memset(g[i&1],0,sizeof g[i&1]);
    		for(j=-k;j<=k;++j)
    			f[i&1][_(j+p[i])]=Add(f[i&1][_(j+p[i])],Mul(f[(i&1)^1][_(j)],inv2)),
    			f[i&1][_(j-p[i])]=Add(f[i&1][_(j-p[i])],Mul(f[(i&1)^1][_(j)],s[i]?M-inv2:inv2)),
    			g[i&1][_(j+p[i])]=Add(g[i&1][_(j+p[i])],Mul(g[(i&1)^1][_(j)],inv2)),
    			g[i&1][_(j-p[i])]=Add(g[i&1][_(j-p[i])],Mul(g[(i&1)^1][_(j)],inv2));
    	}
    	int ans=0,invP=fpow(P);
    	for(i=-P;i<P;++i)ans=Add(ans,Mul(Add(g[n&1][_(i)],M-f[n&1][_(i)]),fpow(Add(1,M-Mul(i,invP)))));
    	return 0*printf("%d
    ",Mul(ans,fpow(2,n)));
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    《观止》读后感
    读产品经理相关书籍有感
    windows phone 7基础点随手记
    Windows phone 7画图画字
    《CLR via C#》读书笔记
    《Beginning C# Objcets》学习笔记
    ASP.NET 使用alert弹出对话框后,CSS样式失效,字体变大的解决方法
    .NET COOKIE /SESSION/CACHE操作类
    【原创】VS2005 Web应用程序打包并安装数据库
    存储过程实现多条件查询
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11245152.html
Copyright © 2020-2023  润新知