LINK


思路

首先因为式子后面把方案数乘上了

所以其实只用输出所有方案的攻击力总和

然后很显然可以用强化牌就尽量用

因为每次强化至少把下面的牌翻一倍,肯定是更优的

然后就只有两种情况

  • 强化牌数量少于k
  • 强化牌数量大于等于k

根据乘法原理,设\(f_{i,j}\)是选i张强化牌用j张的倍数总和,\(g_{i,j}\)是选i张攻击用j张的倍数总和

\(ans+=f_{k,k}*g_{m-i,m-k}\)

\(ans+=f_{i,k-1}*g_{m-i,1}\)

然后f的计算可以量化大小这个东西,就是先排序

dp出选了i个数,最后一个在j的方案数,这样前面的j各种不可能选出其他数,对于后面的数直接组合数计算就可以了


  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int Mod = 998244353;
  4. const int N = 3e3 + 10;
  5. int n, m, k, a[N], b[N], c[N][N];
  6. int sum[N], f[N][N], g[N][N];
  7. int add(int a, int b) {
  8. return (a += b) >= Mod ? a - Mod : a;
  9. }
  10. int mul(int a, int b) {
  11. return 1ll * a * b % Mod;
  12. }
  13. void init() {
  14. for (int i = 0; i < N; i++) c[i][0] = 1;
  15. for (int i = 1; i < N; i++) {
  16. for (int j = 1; j <= i; j++) {
  17. c[i][j] = add(c[i - 1][j], c[i - 1][j - 1]);
  18. }
  19. }
  20. }
  21. int calcf(int a, int b) { // 取a张用b张
  22. if (a < b) return 0;
  23. if (!b) return c[n][a]; //**
  24. int res = 0;
  25. for (int i = 1; i <= n; i++)
  26. res = add(res, mul(f[b][i], c[n - i][a - b]));
  27. return res;
  28. }
  29. int calcg(int a, int b) {
  30. if (a < b) return 0;
  31. if (!b) return 0; //**
  32. int res = 0;
  33. for (int i = 1; i <= n; i++)
  34. res = add(res, mul(g[b][i], c[n - i][a - b]));
  35. return res;
  36. }
  37. void solve() {
  38. scanf("%d %d %d", &n, &m, &k);
  39. for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  40. for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
  41. sort(a + 1, a + n + 1, [&](const int a, const int b) {return a > b;});
  42. sort(b + 1, b + n + 1, [&](const int a, const int b) {return a > b;});
  43. for (int i = 1; i <= n; i++) {
  44. f[1][i] = a[i];
  45. sum[i] = add(sum[i - 1], a[i]);
  46. }
  47. for (int i = 2; i <= n; i++) {
  48. for (int j = i; j <= n; j++)
  49. f[i][j] = mul(sum[j - 1], a[j]);
  50. for (int j = 1; j <= n; j++)
  51. sum[j] = add(sum[j - 1], f[i][j]);
  52. }
  53. for (int i = 1; i <= n; i++) {
  54. g[1][i] = b[i];
  55. sum[i] = add(sum[i - 1], b[i]);
  56. }
  57. for (int i = 2; i <= n; i++) {
  58. for (int j = i; j <= n; j++) {
  59. g[i][j] = add(mul(b[j], c[j - 1][i - 1]), sum[j - 1]);
  60. }
  61. for (int j = 1; j <= n; j++)
  62. sum[j] = add(sum[j - 1], g[i][j]);
  63. }
  64. int ans = 0;
  65. for (int i = max(0, m - n); i <= min(n, m); i++) {
  66. if (i < k) ans = add(ans, mul(calcf(i, i), calcg(m - i, k - i)));
  67. else ans = add(ans, mul(calcf(i, k - 1), calcg(m - i, 1)));
  68. }
  69. printf("%d\n", ans);
  70. }
  71. int main() {
  72. #ifdef dream_maker
  73. freopen("input.txt", "r", stdin);
  74. #endif
  75. init();
  76. int T; scanf("%d", &T);
  77. while (T--) solve();
  78. return 0;
  79. }

LOJ2538. 「PKUWC2018」Slay the Spire【组合数学】的更多相关文章

  1. loj2538 「PKUWC2018」Slay the Spire 【dp】

    题目链接 loj2538 题解 比较明显的是,由于强化牌倍数大于\(1\),肯定是能用强化牌尽量用强化牌 如果强化牌大于等于\(k\),就留一个位给攻击牌 所以我们将两种牌分别排序,企图计算\(F(i ...

  2. loj #2538. 「PKUWC2018」Slay the Spire

    $ \color{#0066ff}{ 题目描述 }$ 九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\) ...

  3. 【LOJ】#2538. 「PKUWC2018」Slay the Spire

    题解 由于强化卡都是大于1的,我们分析一下就会发现,尽可能多的用强化卡,至少用一张攻击卡,一定是每组卡牌的最优选择 所以我们把攻击卡和强化卡从大到小排序 我们设\(g[i][j]\)表示前i张卡牌里选 ...

  4. 「PKUWC2018」Slay the Spire

    题目链接 题意分析 这个题其实不是期望 就是一共有\(C_{2n}^m\)种情况 每一种情况选择\(k\)张牌 然后求最大攻击值的总和 我们考虑 当前抽出了选出了\(i\)张强化牌 \(m-i\)张攻 ...

  5. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

  6. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  7. 「PKUWC2018」随机游走(min-max容斥+FWT)

    「PKUWC2018」随机游走(min-max容斥+FWT) 以后题目都换成这种「」形式啦,我觉得好看. 做过重返现世的应该看到就想到 \(min-max\) 容斥了吧. 没错,我是先学扩展形式再学特 ...

  8. 「PKUWC2018」猎人杀

    「PKUWC2018」猎人杀 解题思路 首先有一个很妙的结论是问题可以转化为已经死掉的猎人继续算在概率里面,每一轮一直开枪直到射死一个之前没死的猎人为止. 证明,设所有猎人的概率之和为 \(W\) , ...

  9. loj#2537. 「PKUWC2018」Minimax

    题目链接 loj#2537. 「PKUWC2018」Minimax 题解 设\(f_{u,i}\)表示选取i的概率,l为u的左子节点,r为u的子节点 $f_{u,i} = f_{l,i}(p \sum ...

随机推荐

  1. Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks论文理解

    一.创新点和解决的问题 创新点 设计Region Proposal Networks[RPN],利用CNN卷积操作后的特征图生成region proposals,代替了Selective Search ...

  2. NHibernate 映射关系

    基本映射关系如下: NHibernate类型 .NET类型 Database类型 备注 AnsiChar System.Char DbType.AnsiStringFixedLength - 1 ch ...

  3. sublime插件安装及常用插件配置

    1.下载 :百度云 工具中 2.注册 sgbteam Single User License EA7E-1153259 8891CBB9 F1513E4F 1A3405C1 A865D53F 115F ...

  4. 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(三)

    六.Feature Layer Feature Layer是一种特殊的Graphics layer(继承自Graphics layer),除了像Graphics layer一样包含和显示Graphic ...

  5. 在WPF中添加Windows Form控件(包括 ocx控件)

      首先,需要向项目中的reference添加两个dll,一个是.NET库中的System.Windows.Forms,另外一个是WindowsFormsIntegration,它的位置一般是在C:\ ...

  6. pip 源 替换国内源

    网上收集来的pip源地址: 阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simp ...

  7. qbxt联赛集训d1t3

    题意 给出一个长度为n的序列,求所有区间的区间最小值乘区间最大值的和.(n<=1e5) solution:

  8. datafile相关(add、rename、drop)

    --case 1 add14:25:04 FPYJ(150_9)@test> alter tablespace fpyj_data02 add datafile '/oradata02/test ...

  9. Eclipse用了官方汉化后,无法输入

    解决方法:Rclipse右键→属性→兼容性→windows vista

  10. php中点击网页不跳转执行程序

    if($code['result_code'] !='FAIL') { echo "<script type='text/javascript'> alert('退款成功,请耐心 ...