首页 > 其他分享 >P4707 重返现世 题解

P4707 重返现世 题解

时间:2024-04-26 21:33:19浏览次数:26  
标签:kMod le 现世 int 题解 sum P4707 bs binom

Description

为了打开返回现世的大门,Yopilla 需要制作开启大门的钥匙。Yopilla 所在的迷失大陆有 \(n\) 种原料,只需要集齐任意 \(k\) 种,就可以开始制作。

Yopilla 来到了迷失大陆的核心地域。每个单位时间,这片地域就会随机生成一种原料。每种原料被生成的概率是不同的,第 \(i\) 种原料被生成的概率是 \(\frac{p_i}{m}\)。如果 Yopilla 没有这种原料,那么就可以进行收集。

Yopilla 急于知道,他收集到任意 \(k\) 种原料的期望时间,答案对 \(998244353\) 取模。

\(1 \le n \le 1000\),\(1 \le k \le n, \lvert n - k \rvert \le 10\),\(0 \le p_i \le m, \sum p = m, 1 \le m \le 10000\)。

Solution

先让 \(k\leftarrow n-k+1\),那么原题相当于求 \(E\left(\text{kMax}(T)\right)\),这玩意可以用 min-max 容斥转化为:

\[\sum_{|S|\geq k}{(-1)^{|S|-k}E\left(\text{Min}(S)\right)\binom{|S|-1}{k-1}} \]

容易发现对于一个集合 \(S\),它的第一次出现的期望就是 \(\dfrac{m}{\sum_{i\in S}{p_i}}\),然后对这个进行 dp 即可。

设 \(f_{i,j,k}\) 表示考虑到了编号 \(1\sim i\),选了 \(j\) 个数,目前和为 \(k\) 的方案数,直接进行 dp 是 \(O(n^2m)\) 的,过不了。

考虑优化。

注意到 \(\sum{p_i}\) 这个东西在分母,所以一定是无法优化掉的,于是可以考虑把个数那一维去掉。

设 \(g_{i,j}\) 表示目前考虑了 \(1\sim i\),和为 \(j\) 的所有方案的 \(\sum{\frac{(-1)^{|S|-k}\binom{|S|-1}{k}}{\sum_{p_i}}}\)。

那么如果 \(i\) 不选,则 \(g_{i,j}\leftarrow g_{i-1,j}\)。

如果 \(i\) 选,会发现哪个组合数不好搞,但是注意到 \(\binom{|S|-1}{k-1}=\binom{|S|-2}{k-1}+\binom{|S|-2}{k-2}\),且前面的 \(-1\) 是好处理的,所以那个组合数也可以 dp 求出。

但是这里 \(k\) 会变化且很小,所以可以记一维 \(k\),即 \(g_{i,j,k}=g_{i-1,j,k}+g_{i-1,j-p_i,k-1}-g_{i-1,j-p_i,k}\)。

边界是 \(g_{0,0,0}=1\)。

时间复杂度:\(O\left(nm(n-k)\right)\)。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 1e3 + 5, kMaxM = 1e4 + 5, kMaxK = 15, kMod = 998244353;

int n, k, m;
int p[kMaxN], f[2][kMaxM][kMaxK];

constexpr int qpow(int bs, int64_t idx = kMod - 2) {
  int ret = 1;
  for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)
    if (idx & 1)
      ret = (int64_t)ret * bs % kMod;
  return ret;
}

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }

void dickdreamer() {
  std::cin >> n >> k >> m;
  k = n - k + 1;
  for (int i = 1; i <= n; ++i) std::cin >> p[i];
  int o = 0;
  f[o][0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    if (!p[i]) continue;
    o ^= 1;
    for (int j = 0; j <= m; ++j)
      for (int s = 0; s <= k; ++s)
        f[o][j][s] = f[o ^ 1][j][s];
    for (int j = p[i]; j <= m; ++j) {
      for (int s = 1; s <= k; ++s) {
        inc(f[o][j][s], sub(f[o ^ 1][j - p[i]][s - 1], f[o ^ 1][j - p[i]][s]));
      }
    }
  }
  int ans = 0;
  for (int i = 1; i <= m; ++i) {
    inc(ans, 1ll * f[o][i][k] * m % kMod * qpow(i) % kMod);
  }
  std::cout << ans << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:kMod,le,现世,int,题解,sum,P4707,bs,binom
From: https://www.cnblogs.com/Scarab/p/18160895

相关文章

  • [题解] [NOIP 2010] 饮水入城
    [题解][NOIP2010]饮水入城题目描述有一个\(n\timesm\)的矩阵,每一点的高度是\(h_{i,j}\)。矩阵的最下面一行是\(m\)个城市,现在要在第一行建水站为这些城市供水,水站建好后水可以从水站往别的点引水,只能从高处引向相邻的低处,如果一个城市存在可以给他引水的水站,则这个城......
  • [题解] [洛谷P4158] 粉刷匠
    [题解][洛谷P4158]粉刷匠题目描述有\(n\)个木板,每个木板有\(m\)个格子,所有格子最开始视为没有颜色。有\(0/1\)两种颜色,每次可以粉刷其中一块木板上一段连续的格子,总共可以粉刷\(t\)次。给出一组目标颜色,问最多可以将多少个格子粉刷成目标颜色。输入格式第一行包含......
  • 列表删除按钮,分页错位问题解决思路 table delete page loadTable
    列表删除按钮,分页错位问题解决思路this.$api('/xxx/xxx/deletexxx',{ids:id}).then(res=>{if(res.status!==20)returnthis.$Message.destroy()this.$Message.success('删除成功')if(this.tableData.leng......
  • node: /lib64/libm.so.6: version `GLIBC_2.27‘ not found问题解决方案
    问题centos7服务器使用nvm或n安装的16以后的高版本node,均会出现以下问题解决1.升级gcc与make#升级GCC(默认为4升级为8)yuminstall-ycentos-release-sclyuminstall-ydevtoolset-8-gcc*ln-s/opt/rh/devtoolset-8/root/bin/gcc/usr/bin/gccln-s/opt/rh/devtool......
  • P10371 「LAOI-4」石头 题解
    原题链接:P10371。首先我们设\(l_{i,0/1}\)表示\(i\)左边的第一,二个比\(a_i\)大的数的位置。\(r_{i,0/1}\)同理。考虑一个区间\([L,R]\)在什么时候满足条件,设\(p,q\)分别为区间中最大/次大值的位置,我们分三种情况讨论。情况一:\(L<p<R\)。考虑从\(L,R\)开......
  • 洛谷题解-官方题单-递归与递推
    P1255数楼梯原题链接题目描述楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶。编一个程序,计算共有多少种不同的走法。对于60%的数据,N≤50;对于100%的数据,1≤N≤5000。思路:每次有2种方法上楼梯,要么上一阶,要么上二阶。第一种:得50分的做法是可以用递归来解:点击查看代码......
  • [题解][2021浙江CCPC] Fair Distribution
    题目描述给定两个数n,m,每次操作可以让n-1或者m+1,求使m%n==0的最少操作数量。题解设进行n-t次操作,使n变成t。若m%t不为0,此时的操作数量为:n-t+t-m%t。若m%t==0,操作数量为n-t。那么只需要枚举t就可以解决此题。但会发现t的范围从1-n过大,考虑将t的范围限制在1-sqrt(m),且每次分别......
  • [题解]P5656 【模板】二元一次不定方程 (exgcd)
    P5656【模板】二元一次不定方程(exgcd)若存在\(ax+by=c\),则可以根据特解\(x,y\)求出任意通解\(x',y'\):\(\begin{cases}x'=x+k*\frac{b}{\gcd(a,b)}\\y'=y-k*\frac{a}{\gcd(a,b)}\end{cases}(k\in\mathbb{Z})\)求特解的方法是「扩展欧几里得(exgcd)」,如果没接触过可以先阅读......
  • [题解][2021浙江CCPC] String Freshman
    题目描述有一份错误的字符串匹配算法,计算S串里有几个T串(只要有一个元素不同,则视为不同的串)。现在输入T串,判断能否构造S串让该算法不通过。intFind_Answer(){intj=1,ans=0;for(inti=1;i<=n;i++){if(S[i]!=T[j])j=1;if(S[......
  • 「实用」如何在洛谷上正确的抄题解
    前言看到这个标题,估计一群人又要开始躁动不安了……等一下,如果是洛谷的管理员看到了这篇文章,不要把我给封了,我是在教各位刚入门的小萌新,也就是以后的神犇们如何切水题呢!本文没有任何反对洛谷的意思,坚决支持kkk!好了,进入今天的正题,“如何在洛谷上正确的抄题解”这个标题直接概括......