UOJ #449. 【集训队作业2018】喂鸽子
UOJ #449. 【集训队作业2018】喂鸽子
小Z是养鸽子的人。一天,小Z给鸽子们喂玉米吃。一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米。一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥k\)。 小Z想要你告诉他,期望多少秒之后所有的鸽子都饱了。
假设答案的最简分数形式为\(\frac{a}{b}\),你需要求出\(w\),满足\(a≡b⋅w \pmod{998244353}(0≤w<998244353).\)
\(n\leq 50,k\leq 1000\)
首先可以用\(\min-\max\)反演来解决:
因为\(k\)是固定的,所以每个集合中至少有一个鸽子被喂饱的期望只与集合大小有关。
\]
其中\(g_c\)就是至少喂饱\(c\)只鸽子中的一只的期望步数。
我们将期望转成概率:
g_c&=\sum_{i\geq 1}i*P(x=i)\\
&=\sum_{i\geq 1}P(x\geq i)\\
\end{align}
\]
设\(f_{c,s}\)表示给\(c\)只鸽子喂食,喂了\(s\)次还没有将任意一只鸽子喂饱的概率。
所以:
g_c&=\sum_{i\geq 1}\sum_{s=0}^{i-1}\binom{i-1}{s}f_{c,s}(\frac{n-c}{n})^{i-1-s}\\
&=\sum_{s=0}^{c(k-1)}f_{c,s}\sum_{t\geq 0}\binom{s+t}{s}(\frac{n-c}{n})^t
\end{align}
\]
我们知道:
\]
所以:
\sum_{t\geq 0}\binom{s+t}{t}(\frac{n-c}{n})^t&=(\frac{1}{1-\frac{n-c}{n}})^{s+1}\\
&=(\frac{n}{c})^{s+1}
\end{align}
\]
所以
\]
接着考虑求\(f\)数组。
方法就是新加进来一只鸽子就枚举给这只鸽子喂了多少次食物。
\frac{f_{c,s}}{s!}=
\sum_{i=0}^{\min(s,k-1)}
\frac{1}{n^ii!}
\frac{ f_{c-1,s-i}}{(s-i!)} \\
\]
于是就可以用\(NTT\)算出\(\frac{f_{c,s}}{s!}\)的值了。
复杂度\(O(n^2klog(k))\)
还有个\(O(n^2k)\)的算法就先咕着吧。
代码:
#include<bits/stdc++.h>
#define ll long long
#define N 55
#define K 1005
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
const ll mod=998244353;
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
}
int n,k,m;
int f[N][N*K];
ll fac[N*K],ifac[N*K];
ll C(int n,int m) {return fac[n]*ifac[m]%mod*ifac[n-m]%mod;}
void NTT(ll *a,int d,int flag) {
static int rev[N*K<<2];
static ll G=3;
int n=1<<d;
for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);
for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int s=1;s<=d;s++) {
int len=1<<s,mid=len>>1;
ll w=flag==1?ksm(G,(mod-1)/len):ksm(G,mod-1-(mod-1)/len);
for(int i=0;i<n;i+=len) {
ll t=1;
for(int j=0;j<mid;j++,t=t*w%mod) {
ll u=a[i+j],v=a[i+j+mid]*t%mod;
a[i+j]=(u+v)%mod;
a[i+j+mid]=(u-v+mod)%mod;
}
}
}
if(flag==-1) {
ll inv=ksm(n,mod-2);
for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;
}
}
ll A[N*K<<2];
ll B[N*K<<2];
ll g[N];
int main() {
n=Get(),k=Get();
m=n*k;
int d=ceil(log2(m+1));
fac[0]=1;
for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
ifac[m]=ksm(fac[m],mod-2);
for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
ll invn=ksm(n,mod-2);
for(int i=0;i<k;i++) {
A[i]=ksm(invn,i)*ifac[i]%mod;
}
NTT(A,d,1);
for(int i=0;i<k;i++) f[1][i]=1;
for(int i=0;i<k;i++) f[1][i]=ksm(invn,i);
for(int i=2;i<=n;i++) {
for(int j=0;j<1<<d;j++) B[j]=0;
for(int j=0;j<=i*(k-1);j++) B[j]=f[i-1][j]*ifac[j];
NTT(B,d,1);
for(int j=0;j<1<<d;j++) B[j]=B[j]*A[j]%mod;
NTT(B,d,-1);
for(int j=0;j<=i*(k-1);j++) f[i][j]=B[j]*fac[j]%mod;
}
for(int i=1;i<=n;i++) {
ll w=ksm(i,mod-2)*n%mod;
ll t=w;
for(int s=0;s<=i*(k-1);s++) {
(g[i]+=f[i][s]*t)%=mod;
t=t*w%mod;
}
}
ll ans=0;
ll flag=1;
for(int c=1;c<=n;c++,flag=flag*(mod-1)%mod) {
(ans+=flag*C(n,c)%mod*g[c])%=mod;
}
cout<<ans;
return 0;
}
UOJ #449. 【集训队作业2018】喂鸽子的更多相关文章
- uoj #450[集训队作业2018]复读机
传送门 \(d=1\),那么任何时刻都可以\(k\)个复读机的一种,答案为\(k^n\) \(d>1\),可以枚举某个复读机的复读次数(必须是\(d\)的倍数),然后第\(i\)个复读时间为\( ...
- UOJ 422 [集训队作业2018] 小Z的礼物 min-max容斥 期望 轮廓线dp
LINK:小Z的礼物 太精髓了 我重学了一遍min-max容斥 重写了一遍按位或才写这道题的. 还是期望多少时间可以全部集齐. 相当于求出 \(E(max(S))\)表示最后一个出现的期望时间. 根据 ...
- 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)
[UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...
- 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)
[UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...
- UOJ#418. 【集训队作业2018】三角形
#418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...
- UOJ#422. 【集训队作业2018】小Z的礼物
#422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...
- UOJ#428. 【集训队作业2018】普通的计数题
#428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...
- uoj450 【集训队作业2018】复读机(生成函数,单位根反演)
uoj450 [集训队作业2018]复读机(生成函数,单位根反演) uoj 题解时间 首先直接搞出单个复读机的生成函数 $ \sum\limits_{ i = 0 }^{ k } [ d | i ] ...
- [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥
题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...
随机推荐
- 第一周Python学习笔记
Python 基本语法: ① Python程序的格式:1.用代码高亮来标识函数丶语句等等 本身的代码高亮并没有实际的意义,只是用来辅助编程人员和阅读人员 更好的识别 2.程序以缩进来标识语句,缩进用 ...
- 微信小程序去除Button默认样式
在小程序开发过程中,使用率蛮高的组件button,因为经常要去除默认样式,然后再自定义样式,所以经常写,自己也总结分享一下简单的实现步骤. (一)实现效果1.实现前(默认样式): 2.实现后(去除默认 ...
- 不带parent指针的successor求解
问题: 请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继).给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值.保证结点的值大于等于 ...
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二九║ Nuxt实战:异步实现数据双端渲染
回顾 哈喽大家好!又是元气满满的周~~~二哈哈,不知道大家中秋节过的如何,马上又是国庆节了,博主我将通过三天的时间,给大家把项目二的数据添上(这里强调下,填充数据不是最重要的,最重要的是要配合着让大家 ...
- Redis in .NET Core 入门:(1) 安装和主要功能简介
Redis(https://redis.io/), 是一个内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 安装Redis 我很少在开发机中直接装各种数据库,我一般使用Docker,针对 ...
- 在linux(centos)系统安装redis教程
最近在切换服务器操作系统,简单记录一下 一.安装redis 1.检查是否有redis yum 源 yum install redis 2.下载fedora的epel仓库 yum install epe ...
- ES 06 - 通过Kibana插件增删改查ES中的索引文档
目录 1 document的结构 2 document的常见CRUD操作 2.1 添加商品: 添加文档并建立索引 2.2 查询商品: 检索文档 2.3 修改商品: 替换文档 2.4 修改商品: 更新文 ...
- 贝塞尔曲线控件 for .NET (EN)
Conmajia 2012 Updated on Feb. 18, 2018 In Photoshop, there is a very powerful feature Curve Adjust, ...
- 树莓派SSH连接快速教程
树莓派系统一般都默认自带ssh 1.首先检查是否安装ssh没 dpkg - l | grep openssh 如果出现几个openssh-xxx,说明你已经安装了 如果没有 2.SSH服务安装 sud ...
- Huffman Tree 简单构造
//函数:构造Huffman树HT[2*n-1] #define MAXVALUE 9999//假设权值不超过9999 #define MAXLEAF 30 #define MAXNODE MAXLE ...