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\)

Orz

首先可以用\(\min-\max\)反演来解决:

因为\(k\)是固定的,所以每个集合中至少有一个鸽子被喂饱的期望只与集合大小有关。
\[ ans=\sum_{i=1}^n(-1)^{i+1}\binom{n}{i}g_i \]
其中\(g_c\)就是至少喂饱\(c\)只鸽子中的一只的期望步数。

我们将期望转成概率:
\[ \begin{align} 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\)次还没有将任意一只鸽子喂饱的概率。

所以:
\[ \begin{align} 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} \]
我们知道:
\[ (\frac{1}{1-x})^k=\sum_{i\geq 0}\binom{i+k-1}{k-1} x^i \]
所以:
\[ \begin{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} \]
所以
\[ g_c=\sum_{s=0}^{c(k-1)}f_{c,s}(\frac{n}{c})^{s+1} \]
接着考虑求\(f\)数组。

方法就是新加进来一只鸽子就枚举给这只鸽子喂了多少次食物。
\[ f_{c,s}=\sum_{i=0}^{\min(s,k-1)}\binom{s}{i}\frac{1}{n^i}f_{c-1,s-i}\\ \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 1005using 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;
}

转载于:https://www.cnblogs.com/hchhch233/p/10745226.html

UOJ #449. 【集训队作业2018】喂鸽子相关推荐

  1. UOJ#449. 【集训队作业2018】喂鸽子

    #449. [集训队作业2018]喂鸽子 DP好题 法一:min-max容斥 处理前m个,最快吃饱的鸽子期望的时间 根据期望的定义 考虑每个方案数的概率*期望次数 枚举前m个用了x个,概率都是(1/m ...

  2. uoj#422. 【集训队作业2018】小Z的礼物

    uoj#422. [集训队作业2018]小Z的礼物 题目描述 Solution 所有礼物全部取到的方案数并不好求,因此我们考虑min−maxmin-maxmin−max容斥,转化为第一次取到集合中某一 ...

  3. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  4. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

  5. UOJ#449. 【集训队作业2018】喂鸽子 min-max容斥,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ449.html 题解 设 f(i) 表示给 i 只鸽子喂食使得至少一只鸽子被喂饱的期望次数,先 min-max容斥 一下. ...

  6. 【集训队作业2018】喂鸽子

    我的计数还是太差了-- 这道题现在知道三种做法. 1. 直接DP 首先显然需要min-max容斥(不知道请百度),不然很难算. 显然对于大小相同的集合答案一样,问题转化为求 \(f_c\) 即 \(c ...

  7. UOJ#419. 【集训队作业2018】圆形(格林公式)

    题面 传送门 题解 首先您得会用格林公式计算圆的面积并 这里只需要动态维护一下圆弧就可以了 时间复杂度\(O(n^2\log n)\) //minamoto #include<bits/stdc ...

  8. UOJ#450. 【集训队作业2018】复读机 排列组合 生成函数 单位根反演

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ450.html 题解 首先有一个东西叫做"单位根反演",它在 FFT 的时候用到过: ...

  9. uoj#420. 【集训队作业2018】矩形(组合数学)

    题面 传送门 题解 这辣鸡题目做了咱整整三天--咱果然还是太菜了--好珂怕的推倒啊-- 首先把它变成 \[\left( \sum_{i = 1}^{n} \sum_{j = 1}^{m} F(i, j ...

  10. uoj#448. 【集训队作业2018】人类的本质(Min_25筛+拉格朗日插值)

    题面 传送门 题解 肝了整整一天--膜拜yww和cx巨巨--(虽然它们的题解里我就没看懂几个字) 请备好草稿纸和笔,这种题目就是需要耐心推倒 题目所求是这么一个东西 \[ \begin{aligned ...

最新文章

  1. 登录之图形跟短信验证码
  2. Redis-17Redis内存回收策略
  3. Quicker--文件搜索工具介绍
  4. 【数据结构与算法】之判断是否互为字符重排
  5. 自动超频_AMD自动超频工具问世:让ZEN2处理器性能上涨、功耗下降
  6. nginx里面的rewrite重写模块详解
  7. vue animation css实现左右折叠面板
  8. 计算机应用综合实践实验心得,综合实践活动培训心得体会范文(精选5篇)
  9. android textview动态居中,android 设置textview文字居中或者控件居中
  10. C语言如何实现模拟栈
  11. IDEA Unmapped Spring configuration files found.
  12. 【java学习之路】(java SE篇)009.IO
  13. 框架-vue-cli
  14. DirectSound---输出设备基本操作(枚举、查询等)
  15. python怎么批量下载图片_批量下载网页图片(python)
  16. 台湾 计算机术语,快取,陣列,程式,这些台湾的计算机术语,你知道几个?|冷知识...
  17. 研发人员如何提高工作效率
  18. 病毒分析 - 特征码提取
  19. Leo的假期学习记录python大数据入门篇(3)
  20. js过滤英文双引号变成中文双引号

热门文章

  1. linux 进程 ldt,LInux 描述符GDT, IDT LDT结构定义
  2. excel 画散点图 怎么设置图片的分辨率_有哪些相见恨晚的Excel图表制作方法?
  3. lodop直接打印服务器的文件,C-Lodop云打印服务器
  4. JAVA提取纯文本_从常见文档中提取纯文本内容 | IT人生录
  5. 华为云服务器怎么更改系统版本,华为云服务器怎么更改系统版本
  6. 做数据分析如何选择适合的数据图表(5类分析方法)
  7. (一)Java网络编程之计网基础、TCP-IP协议簇、TCP、UDP协议及腾讯QQ通信原理综述
  8. 你能发现什么?又能坚持什么?
  9. WebKit介绍及总结(一)
  10. Symbian OS 源码下载方式