zoukankan      html  css  js  c++  java
  • BZOJ 5467 Slay the Spire

    BZOJ 5467 Slay the Spire

    • 我的概率基础也太差了.jpg

    大概就是这样,因为强化牌至少翻倍,所以打出的牌必定是全部的强化牌或者$k-1$个强化牌,然后剩余的机会打出最大的几个攻击牌。

    我们对于强化牌和攻击牌分别做,并且显然,排序并不会影响答案。

    $f[i][j]$表示前$i$张牌,取到$j$张,第$i$张必定取的最大强化值之积,$g[i][j]$表示前$i$张攻击牌,取到$j$张,第$i$张必定取的最大伤害和。(一般来说,应该先考虑第$i$张不必需取的最大值,但是由于那样设计状态并不能优化成$n^2$,所以只能选择第$i$张必须选的答案)

    $f[i][j]=a_i imes sumlimits_{k=j-1}^{i-1} f[k][j-1]$

    $g[i][j]=C(i-1,j-1) imes b_i+sumlimits_{k=j-1}^{i-1} g[k][j-1]$

    然后剩下的就是如何计算答案了。

    那么很显然,我们要求的是前$n$张排中,选择$j$个,第$n$个不必需选择的答案。

    因此设$F(i,j)$表示摸到$i$张,选择$j$个的最大强化之积。那么很显然,$F(i,j)=sumlimits_{k=i}^nf[k][j] imes C(n-k,i-j)$

    同时设$G(i,j)$表示摸到$i$张,选择$j$个的最大伤害之和。那么很显然,$G(i,j)=sumlimits_{k=i}^n g[k][j] imes C(n-k,i-j)$

    同样,根据我们最初得到的结论,$ans=sumlimits_{i=0}^{k-1}F(i,i) imes G(m-i,k-i)+sumlimits_{i=k}^m F(i,k-1) imes G(m-i,1)$

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    #define N 3005
    #define ll long long
    #define mod 998244353
    int f[N][N],g[N][N],n,k,a[N],b[N],m,sum[N],C[N][N];
    void init()
    {
        for(int i=0;i<=3000;i++)
        {
            C[i][0]=1;
            for(int j=1;j<=i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
        }
    }
    int F(int x,int y)
    {
        if(x<y)return 0;if(!y)return C[n][x];int ret=0;
        for(int i=x-y+1;i<=n-y+1;i++)ret=(ret+(ll)f[y][i]*C[i-1][x-y])%mod;
        return ret;
    }
    int G(int x,int y)
    {
        if(x<y)return 0;int ret=0;
        for(int i=x-y+1;i<=n-y+1;i++)ret=(ret+(ll)g[y][i]*C[i-1][x-y])%mod;
        return ret;
    }
    void solve()
    {
        scanf("%d%d%d",&n,&m,&k);
        // memset(f,0,sizeof(f));memset(g,0,sizeof(g));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n-i+1;j++)
                f[i][j]=g[i][j]=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
        sort(a+1,a+n+1);sort(b+1,b+n+1);
        for(int i=1;i<=n;i++)f[1][i]=a[i],sum[i]=(sum[i-1]+a[i])%mod;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<=n-i+1;j++)f[i][j]=(ll)a[j]*(sum[n]-sum[j]+mod)%mod;
            for(int j=1;j<=n-i+1;j++)sum[j]=(sum[j-1]+f[i][j])%mod;
            for(int j=n-i+2;j<=n;j++)sum[j]=sum[j-1];
        }
        for(int i=1;i<=n;i++)g[1][i]=b[i],sum[i]=(sum[i-1]+b[i])%mod;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<=n-i+1;j++)g[i][j]=((ll)b[j]*C[n-j][i-1]+sum[n]-sum[j]+mod)%mod;
            for(int j=1;j<=n-i+1;j++)sum[j]=(sum[j-1]+g[i][j])%mod;
            for(int j=n-i+2;j<=n;j++)sum[j]=sum[j-1];
        }
        int ans=0;
        for(int i=0;i<m;i++)
        {
            if(i<k)ans=(ans+(ll)F(i,i)*G(m-i,k-i))%mod;
            else ans=(ans+(ll)F(i,k-1)*G(m-i,1))%mod;
        }
        printf("%d
    ",ans);
    }
    int main(){init();int T;scanf("%d",&T);while(T--)solve();return 0;}
    
  • 相关阅读:
    MySQL数据库分页
    Spring MVC
    Spring框架
    Java学习计划(转载)
    开发用户注册模块
    Ajax技术
    Jodd Email 发送邮件
    DOM技术
    MD5加密
    final关键字的使用
  • 原文地址:https://www.cnblogs.com/Winniechen/p/10623371.html
Copyright © 2011-2022 走看看