uooogoo' blog

Blog

互测 Round 13 补充题解

2021-10-05 14:05:28 By uooogoo

对不起~ 萌新选手第一次搬题, 出了好大的锅555

把题解搞过来了:

1

第 $x$ 条鱼的答案 =$\sum_{mx=1}^4\sum_{cx=1}^4w_{i,j}*p(x,mx,cx)$

其中 $p(x,mx,cx)$ 表示第 x 条鲳鱼被 第$cx$ 个神佬打死,且$cnt_{mx}>\lfloor \frac {n}{2} \rfloor$的概率

为了计算$p(x,mx,cx)$,我们需要定义一个$f(x,mx,cnt)$表示除了 x 以外的鱼中恰好有 $cnt$ 条鱼被第 $ mx $ 个神佬打死的概率

$p(x,mx,cx)$= $p_{x,cx}$*$\sum_{cnt=\lfloor \frac {n}{2} \rfloor}^nf(x,mx,cnt)$ $cx==mx$

​ $p_{x,cx}$*$\sum_{cnt=\lfloor \frac {n}{2} \rfloor+1}^nf(x,mx,cnt)$ $cx\not=mx$

下面考虑如何计算 $f(x,mx,cnt)$

​ 对于一个给定的 $ mx$ ,现在的问题相当于,第 $i$ 条鲳鱼有 $p_i $的概率被(第$mx$个神佬打死),有 $1-p_i$ 的概率不被(第$mx$个神佬打死),对 $x=1...n$,求除了第 $x$ 条鲳鱼以外恰好有 $cnt $ 条被神佬$mx$打死的概率。

​ 首先我们可以对每一条鱼做一遍dp

​ 枚举除了 $x$ 以外的每条鱼, $dp_{cnt}$ 表示当前集合(即所有已经枚举过的人)恰好杀 $cnt$ 条鱼的概率,假设新加进来的鱼有$p$的概率选,考虑如何更新$dp$数组

​ 令原来的数组为 $dp0$ ,加入这条鱼后的数组为 $dp'$ ,则

$dp'_{cnt}$= $p*dp0_{cnt-1}+(1-p)*dp0_{cnt}$ $cnt>=1$

​ $(1-p)*dp0_{cnt}$ $cnt==0$

​ 因为有 $p$ 的概率多杀了一条鱼,有$1-p$ 的概率不变。

​ 这样时间复杂度是 $O(n^3) $的,期望得分55。

​ 注意到我们不仅支持向集合中加入一条鱼后$O(n)$维护$dp$数组,还支持删除一条鱼后$O(n)$维护$dp$数组。

​ 也就是说,给定 $dp' $和$ p$ ,可以推 $dp0$ 。(注意p=1的情况需要特判)

$dp0_{cnt}$= $\frac {dp'_{cnt}}{1-p}$ $cnt==0$

​ $\frac {dp'_{cnt}-p*dp0_{cnt-1}}{1-p}$ $cnt>=1$

​ 所以先 $O(n^2)$ 求出全集的 $dp$ 数组,然后对每个 $x$ ,$O(n)$ 求出不含$ x$ 的 $dp$ 数组即可,期望得分100。

2

​ 对于一个神佬,$dp$ 求出 $pre_{i,j} $表示前 $i $ 条鱼恰杀 $j$ 条鱼的概率,$ suf_{i,j}$ 表示后 $i$ 条鱼恰杀 $j$ 条鱼的概率。 ​ 考虑求除第 $i$ 条鱼外杀 $>= j $ 条鱼的概率,只需对 $pre$ 求个后缀和,然后枚举即可,复杂度 $O(n^2)$

下面给出标程:

#include<bits/stdc++.h>
#define LL long long
#define clr(x,y) memset(x,y,sizeof(x))
#define FOR(x,l,r) for(int x=l,x##_=r;x<=x##_;x++)
#define FR(x,l,r) for(int x=l,x##_=r;x<x##_;x++)
#define DOR(x,r,l) for(int x=r,x##_=l;x>=x##_;x--)
using namespace std;
const int N=2005;
const int P=998244353;
int n,pos[N][4],A[4][4],dp[N][N],sum[N][N],ans[N];
inline void Add(int &x,int y) {
    x+=y;
    if(x>=P)x-=P;
}
int main() {
    freopen("revolution.in","r",stdin);
    freopen("revolution.out","w",stdout);
    scanf("%d",&n);
    FOR(i,1,n)FOR(j,0,3)scanf("%d",&pos[i][j]);
    FOR(i,0,3)FOR(j,0,3)scanf("%d",&A[i][j]);
    dp[0][0]=sum[n+1][0]=1;
    FOR(id,0,3) {
        FOR(i,1,n)FOR(j,0,i){
            dp[i][j]=(LL)dp[i-1][j]*(P+1-pos[i][id])%P;
            if(j)Add(dp[i][j],(LL)pos[i][id]*dp[i-1][j-1]%P);
        }
        DOR(i,n,1)FOR(j,0,n-i+1){
            sum[i][j]=(LL)sum[i+1][j]*(P+1-pos[i][id])%P;
            if(j)Add(sum[i][j],(LL)pos[i][id]*sum[i+1][j-1]%P);
        }
        FOR(i,1,n)DOR(j,n-i,0)Add(sum[i][j],sum[i][j+1]);
        FOR(i,1,n)FOR(j,0,i-1)FOR(k,0,3)Add(ans[i],(LL)dp[i-1][j]*pos[i][k]%P*A[id][k]%P*sum[i+1][max(0,n/2+1-j-(id==k))]%P);
    }
    FOR(i,1,n)printf("%d\n",ans[i]);
    return 0;
}

Комментарии

No comments yet

Опубликовать комментарий

Вы можете обратиться к mike, используя "@mike", при этом "mike" будет выделено. Если вы хотите набрать символ "@", пожалуйста, используйте "@@".