原文链接www.cnblogs.com/zhouzhendong/p/UOJ449.html

题解

设 f(i) 表示给 i 只鸽子喂食使得至少一只鸽子被喂饱的期望次数,先 min-max容斥 一下。($\frac ni$ 表示期望每 $\frac ni$ 步喂这 i 只鸽子一次)

$$ans = \sum_{i=1}^n (-1)^{i+1}\binom ni \frac ni \cdot f(i)$$

考虑如何求 f(i) 。假设我们喂饱的是第一只鸽子,那么假设我们喂了其他鸽子 j 次,那么就可以得到以下式子:

$$f(i) = \sum_{j=0}^{\infty} (j+k) \binom {j+k-1}{k-1} \cdot \left ( g^{i-1} \right ) ^{(j)} (0)\cdot \frac 1{i^{j+k}}$$

(注: $h^{(a)}(x)$ 表示函数 $h(x)$ 的 a 阶导数,$h^{(a)}(0)$ 表示指数生成函数 $h$ 的第 a 项系数)

其中 $\left(g^{i-1}\right)^{(j)}(0)$ 表示给 i-1 只鸽子喂食,每只喂的次数不超过 k-1 次,总共喂了 j 次的方案数。由于还有一只要强制喂到 k 次,所以要乘上 $\binom{j+k-1}{k-1}$ ,这种情况下喂了 $j+k$ 次鸽子,所以要乘上 $j+k$。

那么这个 g(x) 是什么东西?

对于一只鸽子,可以喂 $0,1,2,\cdots, k-1$ 次,搞一个指数生成函数就好了。

$$ g(x) = \sum_{i=0}^{k-1} \frac{ x^i} {i!}$$

时间复杂度 $O(n^2k \log (nk))$ 。

好像还有一个 $O(n^2k)$ 的神仙做法,先坑着。

代码

#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=55,K=1005,S=1<<16,mod=998244353;
void Add(int &x,int y){
if ((x+=y)>=mod)
x-=mod;
}
void Del(int &x,int y){
if ((x-=y)<0)
x+=mod;
}
int del(int x,int y){
return x-y<0?x-y+mod:x-y;
}
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod)
if (y&1)
ans=(LL)ans*x%mod;
return ans;
}
int Fac[S],Inv[S];
void prework(){
int n=S-1;
for (int i=Fac[0]=1;i<=n;i++)
Fac[i]=(LL)Fac[i-1]*i%mod;
Inv[n]=Pow(Fac[n],mod-2);
Fod(i,n,1)
Inv[i-1]=(LL)Inv[i]*i%mod;
}
int C(int n,int m){
if (m<0||m>n)
return 0;
return (LL)Fac[n]*Inv[m]%mod*Inv[n-m]%mod;
}
int n,k;
int m,d,invm;
int f[N];
int R[S],w[S];
int a[S],b[S],c[S];
void FFT(int *a,int n){
For(i,0,m-1)
if (i<R[i])
swap(a[i],a[R[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=d<<1)
for (int j=0;j<d;j++){
int tmp=(LL)w[t*j]*a[i+j+d]%mod;
a[i+j+d]=del(a[i+j],tmp);
Add(a[i+j],tmp);
}
}
int main(){
prework();
n=read(),k=read();
for (m=1,d=0;m<n*k;m<<=1,d++);
invm=Pow(m,mod-2);
For(i,0,m-1)
R[i]=(R[i>>1]>>1)|((i&1)<<(d-1));
w[0]=1,w[1]=Pow(3,(mod-1)/m);
For(i,2,m-1)
w[i]=(LL)w[i-1]*w[1]%mod;
clr(a);
For(i,0,k-1)
a[i]=Inv[i];
FFT(a,m);
For(i,0,m-1)
b[i]=1;
For(x,1,n){
For(i,0,m-1)
c[i]=b[i];
reverse(w+1,w+m);
FFT(c,m);
reverse(w+1,w+m);
For(i,0,m-1)
c[i]=(LL)c[i]*invm%mod*Fac[i]%mod;
f[x]=0;
For(i,0,m-1)
if (c[i])
Add(f[x],(LL)C(i+k-1,k-1)*c[i]%mod*(i+k)%mod*Pow(x,mod-i-k)%mod);
For(i,0,m-1)
b[i]=(LL)b[i]*a[i]%mod;
}
int ans=0;
For(i,1,n){
int tmp=(LL)C(n,i)*n%mod*Pow(i,mod-2)%mod*f[i]%mod;
if (i&1)
Add(ans,tmp);
else
Del(ans,tmp);
}
cout<<ans<<endl;
return 0;
}

  

UOJ#449. 【集训队作业2018】喂鸽子 min-max容斥,FFT的更多相关文章

  1. UOJ 422 [集训队作业2018] 小Z的礼物 min-max容斥 期望 轮廓线dp

    LINK:小Z的礼物 太精髓了 我重学了一遍min-max容斥 重写了一遍按位或才写这道题的. 还是期望多少时间可以全部集齐. 相当于求出 \(E(max(S))\)表示最后一个出现的期望时间. 根据 ...

  2. uoj #450[集训队作业2018]复读机

    传送门 \(d=1\),那么任何时刻都可以\(k\)个复读机的一种,答案为\(k^n\) \(d>1\),可以枚举某个复读机的复读次数(必须是\(d\)的倍数),然后第\(i\)个复读时间为\( ...

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

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

  4. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

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

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

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

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

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

    #422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...

  8. UOJ#428. 【集训队作业2018】普通的计数题

    #428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...

  9. [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥

    题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...

  10. 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物

    T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...

随机推荐

  1. 20175209 《Java程序设计》第九周学习总结

    20175209 <Java程序设计>第九周学习总结 一.教材知识点总结 有关数据库下载中存在可能出现的问题已经在博客<数据库安装和使用过程中出现的一些问题>给出了相应的解决办 ...

  2. SSM框架中,controller的action返回参数给vue.js

    在SSM框架中,controller的action中,返回的是视图,即jsp页面或是ModelAndView,若是通过axios给vue传值的话,需要转换为字符串或是user实体类对象. 使用@Res ...

  3. 腾讯地图 API 调用入门

    本文仅为腾讯地图 API 调用入门,如需进阶学习,请在腾讯位置服务网站上进行学习. 登陆网址 https://lbs.qq.com/ 点击右上角的登陆按钮,需要进行注册按照流程进行就好. 完成之后,选 ...

  4. python中__str__与__repr__的区别

    __str__和repr __str__和__repr__都是python的内置方法,都用与将对象的属性转化成人类容易识别的信息,他们有什么区别呢 来看一段代码 from math import hy ...

  5. knockoutjs复杂对象的可观察性

    问题 对于一般数据结构: 1. 对于基本类型的数据的变更的可观察性(observable), 可以使用  ko.observable(xxx) 来声明一个 observable对象, 或将其绑定到视图 ...

  6. 使用lombok 注解Java类

    环境信息: IDEA  2016.2.4 Maven 3 JDK 1.8 Maven工程配置: <properties> <lombok.version>1.16.16< ...

  7. 我常用的sublime快捷键整理

    由于很多人用sublime作为编辑器,我想我平时学习的时候也可以用sublime写demo,顺便熟悉一下sublime的使用方法.慢慢发现sublime中快捷键能节省很多时间,很方便,但是同时快捷键很 ...

  8. 查看提交历史(git log)

    git log 命令 在完成了几次提交,或者克隆了一个已有提交历史的仓库后,要查看历史提交记录,可以通过git log命令来实现. $ git log commit 0becea8e1966df258 ...

  9. 伯努利数学习笔记&&Luogu P3711 仓鼠的数学题

    新科技 Luogu P3711 题意 设$ S_{k,n}$表示$ \displaystyle\sum_{i=0}^n i^k$ 求多项式$\displaystyle\sum_{k=0}^n S_{k ...

  10. hash(散列函数)

    一直对哈希不太理解,今天上网搜了一下,总结出以下几点,希望可以对大家的理解有所帮助 1)概念 哈希就是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列 ...