• 牛客网NOIP赛前集训营-提高组(第六场)B-选择题


    题目描述

    有一道选择题,有 a,b,c,d 四个选项。

    现在有 n 个人来做这题,第 i 个人有 pi,j 的概率选第 j 个选项。

    定义(cnt(x))为选第$ x $个选项的人数。

    (mx)(cnt(x))最大的(x)(如果有多个(cnt(x))最大的$ x$,则取其中 (x) 最小的),若 img ,则所有人得 (0) 分;否则令 choicei 表示第$ i $个人选的选项,则第 i 人得 img 分。

    求每个人的期望得分。

    输入描述:

    第一行一个整数 n ,表示人数。

    接下来 n 行,每行 4 个整数,其中第 (i) 行第 (j) 个数表示 (p_{i,j}) ,即在模 (998244353) 意义下第 i 个人选第 j 个选项的概率。

    接下来 4 行,每行 4 个整数,第 (i) 行第 (j) 个数表示 (w_{i,j})

    输出描述:

    共 n 行,第 i 行表示第 i 个人在模 (998244353) 意义下的期望得分。

    示例1

    输入

    2
    499122177 499122177 0 0
    332748118 665496236 0 0
    1 2 3 4
    5 6 7 8 
    9 10 11 12
    13 14 15 16
    

    输出

    166374061
    166374061
    

    说明

    第一个人选第 1,2,3,4 个选项的概率分别为 frac{1}{2},frac{1}{2},0,0

    第二个人选第 1,2,3,4 个选项的概率分别为 frac{1}{3},frac{2}{3},0,0

    当他们选择不同选项时,cnt(mx)=1 le lfloor frac{2}{2} 
floor=1 ,所有人得分为 (0)

    当他们都选第 1 个选项时,概率为 (1/2)*(1/3)=1/6,两个人的得分都是 (w_{1,1}=1)

    当他们都选第 2 个选项时,概率为 frac{1}{2}	imesfrac{2}{3}=frac{1}{3} ,两个人的得分都是 (w_{2,2}=6)

    所以两个人的期望得分都是 frac{1}{6} 	imes 1 + frac{1}{3} 	imes 6=frac{13}{6} , 模 (998244353=166374061)

    Solution

    首先循环枚举每个选项(a)

    我们设(f[i][j])表示前(i)个人有(j)人选了这个选项的概率,(g[i][j])表示后(i)个人有(j)人选了这个选项的概率。转移是很显然的吧。

    [f[i][j]=f[i-1][j-1] imes p[i][a]+f[i-1][j] imes (1-p[i][a])quad f[0][0]=1 ]

    [g[i][j]=g[i+1][j-1] imes p[i][a]+g[i+1][j] imes (1-p[i][a])quad g[n+1][0]=1 ]

    然后我们考虑对(g)的第二维做个后缀和或者对(f) 的第二维做个前缀和。我们拿做(g)来说。那么(g[i][j])的意义就变成了后(i)个人,选了这个选项的人数不少于(j)个的概率。

    然后枚举每一个人,对每一个人,再枚举这个人前面有多少人选这一项,然后下面就不用再说了吧,非常显然的搞一下就好了。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    #define lowbit(x) ((x)&(-(x)))
    #define REP(i,a,n) for(register int i=(a);i<=(n);++i)
    #define PER(i,a,n) for(register int i=(a);i>=(n);--i)
    #define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
    template<typename A>inline void read(A&a){a=0;char c=0;int f=1;while(c<'0'||c>'9')(c=getchar())=='-'?f=-1:0;while(c>='0'&&c<='9')a=(a<<3)+(a<<1)+c-'0',c=getchar();f==-1?a=-a:0;}
    char buf[30];template<typename A>inline void write(A a){if(a<0)putchar('-'),a=-a;int top=0;if(!a)buf[top=1]='0';while(a)buf[++top]=a%10+'0',a/=10;while(top)putchar(buf[top--]);}
    typedef long long ll;typedef unsigned long long ull;
    template<typename A,typename B>inline bool SMAX(A&x,const B&y){return y>x?x=y,1:0;}
    template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;}
    
    const int N=2000+7,MOD=998244353;
    int n,m,p[N][4],w[4][4],f[N][N],g[N][N],ans[N];
    template<typename A,typename B>inline void SADD(A&x,const B&y){x+=y;x>=MOD?x-=MOD:0;}
    
    int main(){
    	read(n);m=(n>>1)+1;
    	for(register int i=1;i<=n;++i)read(p[i][0]),read(p[i][1]),read(p[i][2]),read(p[i][3]);
    	for(register int i=0;i<4;++i)read(w[i][0]),read(w[i][1]),read(w[i][2]),read(w[i][3]);
    	for(register int c=0;c<4;++c){
    		memset(f,0,sizeof(f));memset(g,0,sizeof(g));f[0][0]=1;g[n+1][0]=1;
    		for(register int i=1;i<=n;++i)
    			for(register int j=0;j<=i;++j)f[i][j]=((j?(ll)f[i-1][j-1]*p[i][c]%MOD:0)+(ll)f[i-1][j]*(MOD+1-p[i][c])%MOD)%MOD;
    		for(register int i=n;i;--i)
    			for(register int j=0;j<=n-i+1;++j)g[i][j]=((j?(ll)g[i+1][j-1]*p[i][c]%MOD:0)+(ll)g[i+1][j]*(MOD+1-p[i][c])%MOD)%MOD;
    		for(register int i=1;i<=n;++i)
    			for(register int j=n-i;~j;--j)SADD(g[i][j],g[i][j+1]);
    		for(register int i=1;i<=n;++i){
    			for(register int j=0;j<=i;++j)
    				for(register int k=0;k<4;++k)SADD(ans[i],(ll)f[i-1][j]*g[i+1][m-j-(k==c)>=0?m-j-(k==c):0]%MOD*p[i][k]%MOD*w[c][k]%MOD);
    		}
    	}
    	for(register int i=1;i<=n;++i)write(ans[i]),putchar('
    ');
    }
    
  • 相关阅读:
    《Linux网络安全技术与实现》学习
    OpenGL数据可视化
    CAPWAP简介
    《大话设计模式》学习小结
    《Python数据可视化编程实战》学习总结
    BufferedReader,缓冲输入字符流
    字符流拷贝图片,丢失数据的原因?
    reader,字符流
    BufferedInputSream和BufferedOutputSream,,,
    FileOutputSream
  • 原文地址:https://www.cnblogs.com/hankeke/p/nowcoder-noiptg6-B.html
Copyright © 2020-2023  润新知