首页 > 其他分享 >2022.10.03-D 宝石

2022.10.03-D 宝石

时间:2022-10-15 09:23:59浏览次数:42  
标签:03 frac ifac 宝石 int times fac mul 2022.10

题意:

初始有 \(n\) 种宝石,每种宝石有 \(1\) 颗。

现在你要进行 \(m\) 次操作,每次等概率选择一个宝石,将其复制一遍。

问最后数量最多的前 \(k\) 种宝石的期望数量。

\(n, m, k\le 500\)。


思路

考虑构造一个单调不上升的序列 \(a_1, a_2, ..., a_n\),\(a_i\) 表示某一种宝石被操作的次数。

对这个序列计算它的贡献,则有:

\[(k+\sum_{i=1}^k a_i)\frac{\prod_{i=1}^n a_i!}{n^{\overline{m}}}\times \frac{m!}{\prod_{i=1}^n a_i!} \]

左边的分式计算的是这个序列单次的概率,右边的分式计算的是其对应的操作序列的个数。

如 \(n = 3, m = 3\),对于一种操作序列 \((2, 2, 3)\),其出现的概率为 \(\frac{1}{3}\times\frac{2}{4}\times\frac{1}{5}\)(对应左分式);而与它同类型的操作序列还有 \((2, 3, 2)\) \((3, 2, 2)\)(对应右分式)。

然后我们惊喜地发现,左右分式可以消掉一些项,就直接化成了:

\[(k+\sum_{i=1}^k a_i)\frac{m!}{n^{\overline{m}}} \]

好了,学会计算一种序列单次贡献,那么我们来计算一种序列对应多少种情况。

还是上面的例子,它对应的 \(a\) 序列为 \(2,1,0\),与它相同的操作序列还有 \((1,1,2)\) \((1,1,3)\) \((2,2,1)\) \((3,3,1)\) \((3,3,2)\) 等多种情况。

我们再构造一个序列 \(b_1, b_2, ..., b_m\),\(b_i\) 表示有多少种宝石被恰好操作了 \(i\) 次(可以理解为有多少个 \(a_k=i\))。

那么对于一种 \(a\) 序列,就有一下计算方式:

\[(k+\sum_{i=1}^k a_i)\frac{m!}{n^{\overline{m}}}\times\frac{n!}{\prod_{i=1}^m b_i!} \]

显然,我们可以将 \(m!,~n!,~n^{\overline{m}}\) 提取出来。

对于 \(\prod_{i=1}^m b_i!\),我们考虑用 DP 来计算:

我们设 \(f_{i,j,o}\) 表示我们考虑到同种宝石的操作次数 \(\ge i\),其中有 \(j\) 种宝石已经被选,共进行 \(o\) 次操作的情况。

我们枚举有 \(p\) 种宝石都是操作次数为 \(i\) 的,那么就有转移:

\[f_{i,j+p,o+i*p}\leftarrow \frac{f_{i,j,o}}{p!} \]

而对于 \(j<k,~j+p\ge k\) 的情况,这时候恰好越过了前 \(k\) 大的界限,这时候我们就计算期望,也就是有转移:

\[f_{i,j+p,o+i*p}\leftarrow \frac{f_{i,j,o}}{p!}\times((k-j)\times i+o+k) \]

最后的答案就是 \(f_{0,n,m}\times n!\times m!\times\frac{(n-1)!}{(n+m-1)!}\)


代码

#include<bits/stdc++.h>
#define LL long long
#define FOR(i, x, y) for(int i = (x); i <= (y); i++)
#define ROF(i, x, y) for(int i = (x); i >= (y); i--)
#define PFOR(i, x) for(int i = he[x]; i; i = r[i].nxt)
inline int rd()
{
    int sign = 1, re = 0; char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
    while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
    return sign * re;
}
namespace MOD
{
    const int mod = 998244353;
    inline void add(int &a, int b) {a = a + b >= mod ? a + b - mod : a + b;}
    inline int mul(int a, int b) {return 1ll * a * b % mod;}
    inline int sub(int a, int b) {return a - b < 0 ? a - b + mod : a - b;}
    inline int fast_pow(int a, int b = mod - 2)
    {
        int re = 1;
        while(b)
        {
            if(b & 1) re = mul(re, a);
            a = mul(a, a);
            b >>= 1;
        }
        return re;
    }
} using namespace MOD;
int n, m, kth;
int fac[1005], ifac[1005];
inline void Init()
{
    int N = 1000;
    fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
    FOR(i, 2, N) fac[i] = mul(fac[i - 1], i);
    ifac[N] = fast_pow(fac[N]);
    ROF(i, N - 1, 2) ifac[i] = mul(ifac[i + 1], i + 1);
}
int f[505][505][505];
signed main()
{
    Init();
    n = rd(), m = rd(), kth = rd();
    f[m + 1][0][0] = 1;
    ROF(i, m, 0) FOR(j, 0, n) FOR(k, 0, m) if(f[i + 1][j][k])
        for(int p = 0; j + p <= n && k + i * p <= m; p++)
        {
            if(j < kth && j + p >= kth)
                add(f[i][j + p][k + i * p], mul(mul(f[i + 1][j][k], ifac[p]), k + (kth - j) * i + kth));
            else
                add(f[i][j + p][k + i * p], mul(f[i + 1][j][k], ifac[p]));
        }
    int ans = mul(f[0][n][m], mul(fac[m], fac[n]));
    ans = mul(ans, mul(ifac[n + m - 1], fac[n - 1]));
    printf("%d", ans);
    return 0;
}

标签:03,frac,ifac,宝石,int,times,fac,mul,2022.10
From: https://www.cnblogs.com/zuytong/p/16793568.html

相关文章

  • 2022.10.3-C 旅伴
    题意:有一棵大小为\(n\)的无标号无根树,其中有三种结点:红蓝黄。红色结点的度数最多为\(4\),蓝、黄结点的度数最多为\(3\)。黄色结点之间不能有直接连边。问方案数,\(\b......
  • 2022-09-03-更新日志转移
    layout:postcid:24title:更新日志转移slug:24date:2022/09/0308:03:09updated:2022/09/0308:03:09status:waitingauthor:admincategories:默认分类t......
  • Python Flask报错:TypeError: 'NoneType' object is not subscriptable
    问题:用Flask写了一个请求,用Jmeter请求时报错;但在postman中参数发送,可以成功返回数据以及正常状态码200; 分析:request以json形式发送post请求时,需要headers 解决:he......
  • 【算法训练营day3】LeetCode203. 移除链表元素 707. 设计链表 206. 反转链表
    【算法训练营day3】LeetCode203.移除链表元素707.设计链表206.反转链表LeetCode203.移除链表元素题目链接:203.移除链表元素初次尝试题目比较简单,之前刷过链表的......
  • Linux系统编程03-动态库
    动态库制作命名规则Linux:libxxx.solib:前缀xxx:库的名字.so:后缀Windows:libxxx.dll制作:gcc生成.o文件,得到和位置无关的代码gcc-c-fpic/f......
  • 【闲话】2022.10.14
    今天的考试可算是寄大方了以及:已知T1时限6s,T2T3T4时限均为2s,且每道题都有100个数据点。现在有3页提交。请问Accoders什么时候会炸?真的有一说一,性能不如......
  • 刷题 LeetCode 203 707 206
    代码随想录LeetCode203. 移除链表元素carl链表#dummyNode思路借助dummyNode简化判断条件细节dummyNode方法保持操作一致性LeetCode707. 设计链表carl......
  • 2022.10.14
    今天是我写博客的第一天,首先最重要的就是团队,已经有380人啦,我们的公开赛依然在审核中,已经过去一周了还没有审核好,其次今天在学校里得知我下个星期就要跑1000米了,呜呜呜,而且......
  • 代码随想录算法训练营第三天 | 203.移除链表元素 707.设计链表 206.反转链表
    链表的数据结构基础链表结构链表是一种通过指针串联在一起的线性结构。每一个节点由两钟部分构成,一部分是数据域,一部分是指针域,指针域存放的指针指向另一个节点。链表......
  • 2022.10 杂题
    P8569[JRKSJR6]第七学区首先,有若干种\(O(n\logV)\)的暴力。我们选择其中操作比较简单的一种:对于每一位,先求出所有\(0\)段的长度之和,然后用所有区间的长度之和减掉......