码迷,mamicode.com
首页 > 其他好文 > 详细

loj2538. 「PKUWC2018」Slay the Spire

时间:2019-09-01 21:34:44      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:long   pre   题解   isp   return   ever   scanf   pac   sla   

题意

略。

题解

考虑到尽可能多选强化卡是更优的,所以如果可以,最后只要选最大的一张攻击即可(除非强化卡不够了)。
那么按照这个思路,先把两个序列从大到小排序。
记录\(f_{i, j}\)表示选了\(i\)张强化卡,其中最后一张是第\(j\)张的所有方案的强化倍数的和。
则有
\[ f_{i, j} = a_i \sum_{k = 1} ^ {j - 1} f_{i - 1, k} \]
对于攻击卡也类似。
但这并不是我们想要的。
我们想要的\(F_{i, j}\)应该是分到\(i\)张强化卡,(最优地)最后打出了\(j\)张强化卡的期望强化倍数之和。
因此,计算\(F_{p, q}\)的式子应该是
\[ F_{p, q} = \sum_{i = 1} ^ n f_{i, q} \binom{n - i}{p - q} \]
单组复杂度\(\mathcal O(n ^ 2 + nm)\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3005, mod = 998244353;
int T, n, m, k, ans;
int a[N], b[N], s[N], c[N][N], f[N][N], g[N][N];
void prepare () {
    c[0][0] = 1;
    for (int i = 1; i < N; ++i) {
        c[i][0] = 1;
        for (int j = 1; j <= i; ++j) {
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
        }
    }
}
int F (int p, int q) {
    if (p < q) {
        return 0;
    }
    if (!q) {
        return c[n][p];
    }
    int ret = 0;
    for (int i = 1; i <= n; ++i) {
        ret = (1ll * f[q][i] * c[n - i][p - q] + ret) % mod;
    }
    return ret;
}
int G (int p, int q) {
    if (p < q) {
        return 0;
    }
    int ret = 0;
    for (int i = 1; i <= n; ++i) {
        ret = (1ll * g[q][i] * c[n - i][p - q] + ret) % mod;
    }
    return ret;
}
int main () {
    prepare();
    for (scanf("%d", &T); T; --T) {
        scanf("%d%d%d", &n, &m, &k);
        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), reverse(a + 1, a + n + 1);
        sort(b + 1, b + n + 1), reverse(b + 1, b + n + 1);
        for (int i = 1; i <= n; ++i) {
            f[1][i] = a[i];
            s[i] = (s[i - 1] + a[i]) % mod;
        }
        for (int i = 2; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                f[i][j] = 1ll * a[j] * s[j - 1] % mod;
            }
            for (int j = 1; j <= n; ++j) {
                s[j] = (s[j - 1] + f[i][j]) % mod;
            }
        }
        for (int i = 1; i <= n; ++i) {
            g[1][i] = b[i];
            s[i] = (s[i - 1] + b[i]) % mod;
        }
        for (int i = 2; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                g[i][j] = (1ll * b[j] * c[j - 1][i - 1] + s[j - 1] + mod) % mod;
            }
            for (int j = 1; j <= n; ++j) {
                s[j] = (s[j - 1] + g[i][j]) % mod;
            }
        }
        ans = 0;
        for (int i = 0; i < m; ++i) {
            if (i < k) {
                ans = (1ll * F(i, i) * G(m - i, k - i) + ans) % mod;
            } else {
                ans = (1ll * F(i, k - 1) * G(m - i, 1) + ans) % mod;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

loj2538. 「PKUWC2018」Slay the Spire

标签:long   pre   题解   isp   return   ever   scanf   pac   sla   

原文地址:https://www.cnblogs.com/psimonw/p/11443514.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!