zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj5340:loj2552:uoj399:p4564: [Ctsc2018]假面

    题目大意

    (n)((nleq200))个非负整数(m_1,m_2,...,m_n)((forall iin[1,n],m_ileq100)),有(q)((qleq2*10^5))个操作,每个操作是以下两种之一:
    (1)给出位置(x),概率(q),若(m_x)大于0,则有(q)的概率将(m_x)减一;若(m_x)为0,则不进行任何操作
    (2)给出一个数(k)(k)个不重复的位置(d_1,d_2,...d_k),在(m_{d_1},...,m_{d_k})中随机选一个正数,求选中位置(d_1,...,d_k)的概率各是多少,这种操作不超过1000个
    最后输出每个位置上的数在经过(q)个操作后期望分别是多少。

    题解

    (p_{i,j})表示现在第(i)个数还剩(j)的概率是多少
    在进行操作前,(p_{i,m_i}=1),其他的(p_{i,j})都为0
    如果是操作(1),(x)(q)的概率减一,也就是说,(p_{x,j})(q)的概率转移到(p_{x,j-1})(p_{x,j})(1-q)的概率转移到(p_{x,j}),特殊地,(p_{x,0})(1)的概率转移到(p_{x,0})
    如果是操作(2),设(g_{i,j})表示在不考虑(d_i)时,有(j)个数是正数的概率,那么(d_i)是正数且被选中的概率就是$$(1-p_{d_i,0})(sum_{j=0}^{k-1}g_{i,j}frac{1}{k+1})$$这样,在已知(g)的情况下,就可以在(Theta(k^2))的时间内求出一次(2)操作的答案了
    那么(g)该怎么求呢?设(f_{i,j})表示考虑位置(d_1,...,d_i)位置上的数,其中正数有(j)
    初始(f_{0,0}=1),转移为$$ f_{i,j} egin{cases} f_{i-1,j-1}(1-p_{d_i,0})+f_{i-1,j}p_{d_i,0} & ext {j>0} f_{i-1,j}*p_{d_i,0} & ext{j=0} end{cases} $$
    这样就能求出在这(k)个位置中,有(j)个位置上的数是正数的概率了,但是该如何把这个某个位置上的数的影响去掉,求出(g)呢?
    重新dp一遍想必是不可能的,那样对于每个(d_i)都要重新进行(Theta(k^2))的dp,一次(2)操作就是(Theta(k^3)),时间超限了
    能否用(f)(p)进行一些变化求出(p)呢?会发现在已知(f_{i+1,0},...,f_{i+1,k})(p_{d_{i+1},0})时,是可以求出(f_{i,0},...,f_{i,k})
    先把推出(f_{i+1,0},...,f_{i+1,k})的所有式子写出来:
    (f_{i+1,0}= f_{i,0}*p_{d_{i+1},0})
    (f_{i+1,1}= f_{i,0}*(1-p_{d_{i+1},0})+f_{i,1}*p_{d_{i+1},0})
    (...)
    (f_{i+1,k}= f_{i,k-1}*(1-p_{d_{i+1},0})+f_{i,k}*p_{d_{i+1},0})
    再把(f_{i,0},...,f_{i,k})拿到左边:
    (f_{i,0}= frac{f_{i+1,0}}{p_{d_{i+1},0}})
    (f_{i,1}= frac{f_{i+1,1}-f_{i,0}*(1-p_{d_{i+1},0})}{p_{d_{i+1},0}})
    (...)
    (f_{i,k}= frac{f_{i+1,k}-f_{i,k-1}*(1-p_{d_{i+1},0})}{p_{d_{i+1},0}})
    特殊地,当(p_{d_{i+1},0}=0)时,(f_{i,j}=f_{i+1,j+1})
    这个变化的复杂度是(Theta(k))
    (f_{i+1,...})本来是(d_1,..,d_{i+1})的答案,经过变化后,(f_{i,...})(d_1,..,d_{i})的答案,这相当于把(d_{i+1})位置上的数的影响从(f_{i+1,...})中去掉
    那么(g_{i,...})可以看成把(d_i)位置上的数的影响从(f_{n,...})中删去,就可以进行相似的变化
    (p_{d_{i+1},0} eq 0)时,
    (g_{i,0}= frac{f_{n,0}}{p_{d_{i+1},0}})
    (g_{i,1}= frac{f_{n,1}-g_{i,0}*(1-p_{d_{i+1},0})}{p_{d_{i+1},0}})
    (...)
    (g_{i,k}= frac{f_{n,k}-g_{i,k-1}*(1-p_{d_{i+1},0})}{p_{d_{i+1},0}})
    (p_{d_{i+1},0}=0)时,(g_{i,j}=f_{g,j+1})

    代码
    #include<algorithm>
    #include<cmath>
    #include<complex>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define maxn 210 
    #define maxm 110
    #define LL long long
    using namespace std;
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    void write(int x)
    {
    	if(x==0){putchar('0');return;}
    	int f=0;char ch[20];
    	if(x<0)putchar('-'),x=-x;
    	while(x)ch[++f]=x%10+'0',x/=10;
    	while(f)putchar(ch[f--]);
    	return;
    }
    const LL mod=998244353;
    int inv[maxn],n,q,m[maxn],p[maxn][maxm],f[2][maxn],g[maxn],id[maxn],yes[maxn],no[maxn],num;
    int qp(int x,int y){int ans=1;while(y){if(y&1)ans=(LL)ans*(LL)x%mod;x=(LL)x*(LL)x%mod,y>>=1;}return ans;}
    void work()
    {
    	rep(i,1,num)f[0][i]=0;f[0][0]=1;
    	rep(i,0,num-1)
    	{
    		int now=i&1,nxt=now^1;
    		rep(j,0,i)
    		{
    			f[nxt][j+1]=((LL)f[nxt][j+1]+(LL)f[now][j]*(LL)yes[i+1]%mod)%mod;
    			f[nxt][j]=((LL)f[nxt][j]+(LL)f[now][j]*(LL)no[i+1]%mod)%mod;
    			f[now][j]=0;
    		}
    	}
    	rep(i,1,num)
    	{
    		int res=0,fdie=qp(no[i],mod-2); 
    		if(no[i]!=0)
    		{
    			g[0]=(LL)f[num&1][0]*(LL)fdie%mod; 
    			rep(j,1,num-1)g[j]=(f[num&1][j]-(LL)g[j-1]*(LL)yes[i]%mod+mod)%mod*(LL)fdie%mod;
    		}
    		else
    		{
    			rep(j,0,num-1)g[j]=f[num&1][j+1];
    		}
    		rep(j,0,num-1)res=(res+(LL)yes[i]*(LL)g[j]%mod*(LL)inv[j+1]%mod)%mod;
    		write(res);
    		if(i!=num)putchar(' '); 
    	}
    	rep(i,0,num)f[num&1][i]=0;
    	putchar('
    ');
    }
    int main()
    {
    	n=read();
    	rep(i,1,n)m[i]=read(),p[i][m[i]]=1,inv[i]=qp(i,mod-2);
    	q=read();
    	while(q--)
    	{
    		int op=read();
    		if(op)
    		{
    			num=read();
    			rep(i,1,num)id[i]=read();
    			rep(i,1,num)no[i]=p[id[i]][0],yes[i]=(1-p[id[i]][0]+mod)%mod;
    			work();
    		}
    		else
    		{
    			int x=read(),u=read(),v=read(),die=(LL)u*(LL)qp(v,mod-2)%mod,live=(LL)(v-u)%mod*(LL)qp(v,mod-2)%mod;
    			rep(i,1,m[x])p[x][i-1]=(p[x][i-1]+(LL)p[x][i]*(LL)die%mod)%mod,p[x][i]=(LL)p[x][i]*(LL)live%mod;
    		}
    	}
    	rep(i,1,n)
    	{
    		int res=0;
    		rep(j,1,m[i])res=(res+(LL)j*(LL)p[i][j]%mod)%mod;
    		write(res);
    		if(i!=n)putchar(' ');
    	}
    	return 0;
    }
    
    
    一些意见

    第一次见需要对dp结果去掉一个决策的影响的题
    以及今天学会设置友链了!

  • 相关阅读:
    UVALive 6909 Kevin's Problem 数学排列组合
    UVALive 6908 Electric Bike dp
    UVALive 6907 Body Building tarjan
    UVALive 6906 Cluster Analysis 并查集
    八月微博
    hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形
    hdu 5792 World is Exploding 树状数组
    hdu 5791 Two dp
    hdu 5787 K-wolf Number 数位dp
    hdu 5783 Divide the Sequence 贪心
  • 原文地址:https://www.cnblogs.com/xzyf/p/10037375.html
Copyright © 2011-2022 走看看