• codeforces Nauuo and Pictures


    题目描述

    题解

    暴力永远不是题解的暴力

    考虑暴力dp: $f_w[i][j][k]$ 表示目前权值是 $w$ 且 $w$ 是喜欢的,喜欢的和为 $j$ ,不喜欢的为 $k$ , $i$ 轮后的期望值, $g_w[i][j][k]$ 是类似的,只是 $w$ 是不喜欢的

    考虑转移: $f_w[i][j][k]=frac{w}{j+k} imes f_{w+1}[i-1][j+1][k]+frac{j-w}{j+k} imes f_w[i-1][j+1][k]+frac{k}{j+k} imes f_w[i-1][j][k-1]$

    然后我们可以证明 $f_w[i][j][k]=wf_1[i][j][k]$ ,证明的话就用数学归纳法,就是 $f_w[i-1][j][k]=wf_1[i-1][j][k]$ ,然后把式子化开就能证了

    所以我们现在只需要求 $f_1[i][j][k]$ ,同时我们发现 $j,k$ 状态的加减次数和 $m-i$ 相同,所以我们可以设计dp: $f[i][j]$ 表示喜欢的被选了几次,不喜欢的被选了几次,当前权值为 $1$ ,在 $m-j-k$ 轮后的期望值,然后和上面的转移类似,可以预处理逆元将效率达到 $O(n+mlogP+m^2)$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e6+5,M=3005,P=998244353;
    int n,m,a[N],b[N],w[N],c[2],f[M][M],g[M][M];
    int K(int x,int y){
        int z=1;
        for (;y;y>>=1,x=1ll*x*x%P)
            if (y&1) z=1ll*z*x%P;
        return z;
    }
    int main(){
        cin>>n>>m;
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for (int i=1;i<=n;i++)
            scanf("%d",&w[i]),c[a[i]]+=w[i];
        for (int i=max(m-c[0]-c[1],0);i<=m+m;i++)
            b[i]=K(c[0]+c[1]+i-m,P-2);
        for (int i=m;~i;i--){
            f[i][m-i]=g[i][m-i]=1;
            for (int j=min(m-i-1,c[0]);~j;j--)
                f[i][j]=1ll*(1ll*(c[1]+i+1)*f[i+1][j]%P+1ll*(c[0]-j)*f[i][j+1]%P)*b[i-j+m]%P,
                g[i][j]=1ll*(1ll*(c[1]+i)*g[i+1][j]%P+1ll*(c[0]-j-1)*g[i][j+1]%P)*b[i-j+m]%P;
        }
        for (int i=1;i<=n;i++)
            printf("%lld
    ",1ll*w[i]*(a[i]?f[0][0]:g[0][0])%P);
        return 0;
    }
  • 相关阅读:
    hihocoder-1014 Trie树
    51Nod-1265 四点共面
    cf466B Wonder Room
    2014.9.13模拟赛【数位和乘积】
    2014.9.13模拟赛【环上的游戏】
    bzoj2719[Violet 4]银河之星
    wikioi1450 xth的旅行
    poj2352 stars
    2014.9.6模拟赛【藏妹子之处】
    2014.9.6模拟赛【工资】
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12297087.html
Copyright © 2020-2023  润新知