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

4 篇文章 0 订阅
1 篇文章 0 订阅

题目链接

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

题目描述

一道选择题有四个选项,有 n n n 个人来做这题,第 i i i 个人有 p i , j p_{i,j} pi,j 的概率选第 j j j 个选项。定义 c n t x cnt_x cntx为选第 x x x 个选项的人数。令 m x mx mx c n t x cnt_x cntx 最大的 x x x ( ( (如果有多个最大 c n t x cnt_x cntx x x x,则取其中 x x x 最小的),若 c n t m x ≤ ⌊ n 2 ⌋ cnt_{mx}\le\lfloor\frac{n}{2}\rfloor cntmx2n,则所有人得 0 0 0 分;否则令 c h o i c e i choice_i choicei 表示第 i i i 个人选的选项,则第 i i i 人得 w m x , c h o i c e i w_{mx,choice_i} wmx,choicei 分。求每个人的期望得分。 n ≤ 2000 n\le 2000 n2000

解题思路

由于题目中说明 c n t m x ≤ ⌊ n 2 ⌋ cnt_{mx}\le \lfloor\frac{n}{2}\rfloor cntmx2n 是没有得分的,在期望的角度上可以看作这种情况没有贡献。那么,有贡献的当且仅当有 m x mx mx 使得 c n t m x > ⌊ n 2 ⌋ cnt_{mx} > \lfloor\frac{n}{2}\rfloor cntmx>2n,所以我们考虑枚举 m x mx mx

t   ( t ← 1 ∼ 4 ) t\ (t \leftarrow 1\sim4) t (t14) 为当前选择的人数最多的选项,考虑 dp \text{dp} dp

f i , j f_{i,j} fi,j 表示前 i i i 个人, j j j 个人选择了 t t t 这个选项的概率,那我们分两种情况转移:
f i , j = { f i − 1 , j × ( 1 − p i , t ) → 第 i 个 人 不 选 t 选 项 f i − 1 , j − 1 × p i , t → 第 i 个 人 选 t 选 项 f_{i,j}=\begin{cases}f_{i-1,j}\times(1-p_{i,t})\rightarrow 第i个人不选t选项\\f_{i-1,j-1}\times p_{i,t}\rightarrow 第i个人选t选项\end{cases} fi,j={fi1,j×(1pi,t)itfi1,j1×pi,tit
设计好这个 dp \text{dp} dp 状态后感觉有点无从下手,这个 dp \text{dp} dp 不能算出方案和每个人得分的期望。考虑对每个第 i i i 个人枚举他所选的选项 k k k,根据选择人数最多的 t t t 选项和 dp \text{dp} dp 数组 f f f,可以推出前 i i i 个,但是对于后面的选择方案还是难处理,所以再引入一个 g g g 数组,去 dp \text{dp} dp 出后面的概率。

首先令 g i , j g_{i,j} gi,j 表示第 i ∼ n i\sim n in 人, j j j 个人选择了 t t t 这个选项的概率,也分两种情况转移:
g i , j = { g i + 1 , j × ( 1 − p i , t ) → 第 i 个 人 不 选 t 选 项 g i + 1 , j − 1 × p i , t → 第 i 个 人 选 t 选 项 g_{i,j}=\begin{cases}g_{i+1,j}\times (1-p_{i,t})\rightarrow 第i个人不选t选项\\g_{i+1,j-1}\times p_{i,t}\rightarrow 第i个人选t选项\end{cases} gi,j={gi+1,j×(1pi,t)itgi+1,j1×pi,tit
由于题目里要求是 > ⌊ n 2 ⌋ >\lfloor\frac{n}{2}\rfloor >2n,所以假如去枚举 ⌊ n 2 ⌋ + 1 ∼ n \lfloor\frac{n}{2}\rfloor+1\sim n 2n+1n 的每个 j j j,叠加 g i , j g_{i,j} gi,j,显然会超时,那么我们只需要做后缀和,将 dp \text{dp} dp 数组 g g g 的含义改为:第 i ∼ n i\sim n in 人, ≥ j \ge j j 个人选择了 t t t 这个选项的概率。只需要 g i , j = g i , j + g i , j + 1 g_{i,j}=g_{i,j}+g_{i,j+1} gi,j=gi,j+gi,j+1 就可以了。

算出 f , g f,g f,g 后, O ( 4 n 2 ) O(4n^2) O(4n2) 枚举,考虑到第 i i i 个人,前 i − 1 i-1 i1 个人中 j j j 个选择了 t t t 这个选项,当前人选择的选项,对第 i i i 人得分的贡献 ( i (i (i枚举当前考虑到的人, j j j枚举 i i i前面的人中 j j j个选择 t t t选项, k k k枚举当前第 i i i人的选项 ) ) ) f i − 1 , j × p i , k × w t , k × g i + 1 , max ⁡ ( 0 , ⌊ n 2 ⌋ + 1 − [ t = = k ] ) f_{i-1,j}\times p_{i,k}\times w_{t,k}\times g_{i+1,\max(0,\lfloor\frac{n}{2}\rfloor+1-[t==k])} fi1,j×pi,k×wt,k×gi+1,max(0,2n+1[t==k])。表示前 i − 1 i-1 i1 j j j 人选择 t t t 的概率 × \times ×当前第 i i i 人选择 k k k 的概率 × \times ×当前情况的得分贡献 × \times ×想要使得 c n t m x > ⌊ n 2 ⌋ cnt_{mx}>\lfloor\frac{n}{2}\rfloor cntmx>2n i + 1 ∼ n i+1\sim n i+1n 的合法钦定选项方案的概率。总时间复杂度 O ( 16 n 2 ) O(16n^2) O(16n2)

代码实现

#include<bits/stdc++.h>
#define For(i,a,b)for(int i=a;i<=b;i++)
#define Forr(i,a,b)for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int N=2005,mod=998244353;
int n,H;ll A[N],a[N][5],b[5][5],f[N][N],g[N][N];
inline int read(){
	char c=getchar();int x=0,f=1;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
int main(){
	n=read();For(i,1,n)For(j,1,4)a[i][j]=read();For(i,1,4)For(j,1,4)b[i][j]=read();f[0][0]=g[n+1][0]=1,H=(n>>1)+1;
	For(t,1,4){
        For(i,1,n)For(j,0,i)f[i][j]=(1ll*f[i-1][j]*(1-a[i][t]+mod)%mod+(j>0)*1LL*a[i][t]*f[i-1][j-1]%mod)%mod;
        Forr(i,n,1)For(j,0,n-i+1)g[i][j]=(1ll*g[i+1][j]*(1-a[i][t]+mod)%mod+(j>0)*1ll*a[i][t]*g[i+1][j-1]%mod)%mod;
		For(i,1,n)Forr(j,n-i,0)g[i][j]=(g[i][j]+g[i][j+1])%mod;
		For(i,1,n)For(j,0,i-1)For(k,1,4)A[i]=(A[i]+1ll*f[i-1][j]*a[i][k]%mod*b[t][k]%mod*g[i+1][max(0,H-j-(t==k))]%mod)%mod;
	}
	For(i,1,n)printf("%lld\n",A[i]);return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值