UOJ#449 喂鸽子
题意:有n个鸽子,你每秒随机喂一只鸽子,每只鸽子吃k次就饱了。求期望多少秒之后全饱了。n <= 50, k <= 1000。
解:有两种做法。一种直接DP的n2k做法在这。我用的是Min-Max容斥 + NTT优化DP。
先Min-Max容斥,由于鸽子是等价的,所以相当于求m只鸽子期望多少秒之后有一只饱了。
讲不清楚...看题解吧。

注意题解中m个盒子的答案为什么放了i + 1个球,这是因为我们把最后一个球拿出来考虑了。所以唯一放满k个球的盒子的贡献是1 / (k - 1)!
#include <bits/stdc++.h> const int MO = ;
const int N = ; int n, K, fac[N], inv[N], invn[N];
int f[][N], g[][N], A[N * ], B[N * ], r[N * ]; inline int C(int n, int m) {
if(n < || m < || n < m) return ;
return 1ll * fac[n] * invn[m] % MO * invn[n - m] % MO;
} inline int qpow(int a, int b) {
int ans = ;
while(b) {
if(b & ) ans = 1ll * ans * a % MO;
a = 1ll * a * a % MO;
b = b >> ;
}
return ans;
} inline int Inv(int x) {
return qpow(x, MO - );
} inline void prework(int n) {
static int R = ;
if(R == n) return;
R = n;
int lm = ;
while(( << lm) < n) lm++;
for(int i = ; i < n; i++) {
r[i] = (r[i >> ] >> ) | ((i & ) << (lm - ));
}
return;
} inline void NTT(int *a, int n, int f) {
prework(n);
for(int i = ; i < n; i++) {
if(i < r[i]) {
std::swap(a[i], a[r[i]]);
}
}
for(int len = ; len < n; len <<= ) {
int Wn = qpow(, (MO - ) / (len << ));
if(f == -) Wn = Inv(Wn);
for(int i = ; i < n; i += (len << )) {
int w = ;
for(int j = ; j < len; j++) {
int t = 1ll * a[i + len + j] * w % MO;
a[i + len + j] = (a[i + j] - t) % MO;
a[i + j] = (a[i + j] + t) % MO;
w = 1ll * w * Wn % MO;
}
}
}
if(f == -) {
int inv = Inv(n);
for(int i = ; i < n; i++) {
a[i] = 1ll * a[i] * inv % MO;
}
}
return;
} int main() { scanf("%d%d", &n, &K); fac[] = inv[] = invn[] = ;
fac[] = inv[] = invn[] = ;
for(int i = ; i <= n * K; i++) {
fac[i] = 1ll * fac[i - ] * i % MO;
inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO;
invn[i] = 1ll * invn[i - ] * inv[i] % MO;
} int len = ;
while(len <= n * K) len <<= ;
g[][] = ;
memcpy(B, invn, K * sizeof(int));
NTT(B, len, );
for(int i = ; i <= n; i++) {
/*for(int j = 0; j <= i * K; j++) {
/// g[i][j] f[i][j]
for(int k = 0; k < K && k <= j; k++) {
g[i][j] = (g[i][j] + 1ll * g[i - 1][j - k] * invn[k] % MO) % MO;
f[i][j] = (f[i][j] + 1ll * f[i - 1][j - k] * invn[k] % MO) % MO;
}
if(j >= K) f[i][j] = (f[i][j] + 1ll * g[i - 1][j - K] * invn[K - 1] % MO) % MO;
}*/
memcpy(A, g[i - ], n * K * sizeof(int));
memset(A + n * K, , (len - n * K) * sizeof(int));
NTT(A, len, );
for(int j = ; j < len; j++) {
A[j] = 1ll * A[j] * B[j] % MO;
}
NTT(A, len, -);
for(int j = ; j <= i * K; j++) {
g[i][j] = A[j];
}
memcpy(A, f[i - ], n * K * sizeof(int));
memset(A + n * K, , (len - n * K) * sizeof(int));
NTT(A, len, );
for(int j = ; j < len; j++) {
A[j] = 1ll * A[j] * B[j] % MO;
}
NTT(A, len, -);
for(int j = ; j <= i * K; j++) {
f[i][j] = A[j];
if(j >= K) {
f[i][j] = (f[i][j] + 1ll * g[i - ][j - K] * invn[K - ] % MO) % MO;
}
}
} int ans = ;
for(int i = ; i <= n; i++) {
int temp = ;
for(int j = K - ; j <= i * K; j++) {
temp = (temp + 1ll * fac[j - ] * f[i][j] % MO * qpow(inv[i], j) % MO * j % MO) % MO;
}
temp = 1ll * temp * n % MO * inv[i] % MO * C(n, i) % MO;
if(i & ) {
ans = (ans + temp) % MO;
}
else {
ans = (ans - temp) % MO;
}
}
printf("%d\n", (ans + MO) % MO);
return ;
}
AC代码
UOJ#449 喂鸽子的更多相关文章
- UOJ #449. 【集训队作业2018】喂鸽子
UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...
- UOJ#449. 【集训队作业2018】喂鸽子(期望dp)
题意 有 \(n\) 只鸽子,每只鸽子需要 \(k\) 粒玉米才能喂饱.问每次随意喂给 \(n\) 个鸽子中的一个,期望多久所有鸽子都被喂饱. 对于 \(998244353\) 取模. 数据范围 \( ...
- UOJ#449. 【集训队作业2018】喂鸽子 min-max容斥,FFT
原文链接www.cnblogs.com/zhouzhendong/p/UOJ449.html 题解 设 f(i) 表示给 i 只鸽子喂食使得至少一只鸽子被喂饱的期望次数,先 min-max容斥 一下. ...
- UOJ 449 【集训队作业2018】喂鸽子 【生成函数,min-max容斥】
这是第100篇博客,所以肯定是要水过去的. 首先看到这种形式的东西首先min-max容斥一波,设\(f_{c,s}\)表示在\(c\)只咕咕中,经过\(s\)秒之后并没有喂饱任何一只的概率. \[ \ ...
- @noi.ac - 443@ 老头子的话
目录 @description@ @solution@ @accepted code@ @details@ @description@ 老头子是小学校长,小学生(大哥)们都很听老头子的话.一天,老头子 ...
- @atcoder - AGC038E@ Gachapon
目录 @description@ @solution - 1@ @accepted code - 1@ @solution - 2@ @accepted code - 2@ @details@ @de ...
- 【UOJ#386】【UNR#3】鸽子固定器(贪心)
[UOJ#386][UNR#3]鸽子固定器(贪心) 题面 UOJ 题解 一个不难想到的暴力做法是把东西按照\(s\)排序,这样子我们枚举极大值和极小值,那么我们选择的一定是这一段之间\(v\)最大的那 ...
- UOJ#386. 【UNR #3】鸽子固定器(链表)
题意 题目链接 为了固定S**p*鸽鸽,whx和zzt来到鸽具商店选购鸽子固定器. 鸽具商店有 nn 个不同大小的固定器,现在可以选择至多 mm 个来固定S**p*鸽鸽.每个固定器有大小 sisi 和 ...
- UOJ.386.[UNR #3]鸽子固定器(贪心 链表)
题目链接 \(Description\) 选最多\(m\)个物品,使得它们的\((\sum vi)^{dv}-(s_{max}-s_{min})^{du}\)最大. \(Solution\) 先把物品 ...
随机推荐
- oracle 删除掉重复数据只保留一条
用SQL语句,删除掉重复项只保留一条 在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢 .查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select ...
- Byte[]和Stream相互转换
C# Stream 和 byte[] 之间的转换 一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Ima ...
- NPM 使用介绍(包管理工具,解决NodeJS代码部署上的很多问题)
引用地址:http://www.runoob.com/nodejs/nodejs-npm.html NPM 使用介绍 NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问 ...
- Python3升级3.6强力Django+杀手级xadmin打造在线教育平台✍✍✍
Python3升级3.6强力Django+杀手级xadmin打造在线教育平台 教程 Xadmin安装方法: settings.py 的配置: users App 下的 adminx.py 的配置:
- Go前言
Go语言为并发而生 硬件制造商正在为处理器添加越来越多的内核以来提高性能.所有数据中心都在这些处理器上运行,今天的应用程序使用多个微服务来维护数据库连接,消息队列和维护缓存.所以,开发的软件和编程语言 ...
- java_List接口
/** * java.util.list接口 extends Collection接口 * 1.有序的集合 * 2.有索引 * 3.元素可以重复 * * List中带索引的方法: *add:添加 * ...
- MVC中DropDownListFor的使用注意事项
1.在MVC的View页面中使用DropDownListFor时当DropDownListFor是列表是通过后台ViewBag传过来时,当ViewBag中的Key与DropDownListFor一致时 ...
- 满血复活前的记录(持续更新ing)
时隔一年重新开启算法竞赛征程. 该记录大多为老课件.已经做过的习题重做和已经看过的书本重看 7.21 下午到山大 娄晨耀basic_algorithm课件中的内容: 复习线性筛原理 复习差分 做完Co ...
- Android开发 音视频开发需要了解的专业术语知识
前言 在摸索一段时间的音视频开发后,越来越发现这个坑的深度真是特别的深. 除了了解Android自带的音视频处理API以外,还得了解一些视频与音频方面的知识.这篇博客就是主要讲解这方面的专业术语.内容 ...
- 2016.9.17初中部下午NOIP普及组比赛总结
2016.9.17初中部下午NOIP普及组比赛总结 2016.09.17[初中部 NOIP普及组 ]模拟赛 最近几次的题目都不是自己擅长的啊... 不过含金量挺高的,也好... 进度: 比赛:0+0+ ...