Description

给定 n n n个正整数 a i a_i ai​,令 N + 1 = ∑ a i N+1=\sum a_i N+1=∑ai​
将执行 N N N次操作,每次等概率随机选择一个非零的 a i a_i ai​并令其减一,显然 N N N次操作结束之后有且仅有一个 a i = 1 a_i=1 ai​=1
对于一开始的 n n n个 a i a_i ai​,分别求出它们最后为 1 1 1的概率
n , a i ≤ 30 n,a_i \leq 30 n,ai​≤30

Analysis

写这题时作死没开longlong,结果还是被乘法忘记转longlong坑死了
以后这种题无脑上longlong,千万别玩火
每次选择非零 a i a_i ai​减一,每次操作概率会更改,不好统计答案。
考虑将操作转化成,随机选择 a i a_i ai​,若 a i > 0 a_i>0 ai​>0则令其减一,否则继续随机,显然答案等价。这样每次操作的每个 a i a_i ai​被选中的概率都是 1 / n 1/n 1/n
使用EGF来描述操作序列,为了方便计算,我们把最后一个剩下的数也加入操作序列。不妨假设最后剩下的是 a 1 a_1 a1​
对于 2 ≤ i ≤ n 2\leq i\leq n 2≤i≤n, i i i至少出现 a i a_i ai​次;对于 1 1 1, 1 1 1恰好出现 a 1 a_1 a1​次,且一定在序列末出现
令 G k ( x ) = ∑ i = 0 a k − 1 x i i ! G_k(x)=\sum_{i=0}^{a_k-1}\frac{x^i}{i!} Gk​(x)=∑i=0ak​−1​i!xi​,那么合法序列(除最后一项)的EGF就是
F ( x ) = x a 1 − 1 ( a 1 − 1 ) ! ∏ i ≠ 1 ( e x − G i ( x ) ) F(x)=\frac{x^{a_1-1}}{(a_1-1)!}\prod_{i\neq 1}(e^x-G_i(x)) F(x)=(a1​−1)!xa1​−1​i̸​=1∏​(ex−Gi​(x))
答案即为
∑ i ≥ 0 i ! [ x i ] F ( x ) n i + 1 \sum_{i\geq 0}\frac{i![x^i]F(x)}{n^{i+1}} i≥0∑​ni+1i![xi]F(x)​
将 F ( x ) F(x) F(x)展开,每部分形如 λ x d e j x \lambda x^d e^{jx} λxdejx,其中 λ \lambda λ可以 d p dp dp求出,考虑计算该部分对答案的贡献
λ n d + 1 ∑ i ≥ 0 j i ( d + i ) ! i ! n i \frac{\lambda}{n^{d+1}} \sum_{i\geq 0}\frac{j^i (d+i)!}{i!n^i} nd+1λ​i≥0∑​i!niji(d+i)!​
= λ d ! n d + 1 ∑ i ≥ 0 ( j n ) i ( d + i i ) =\frac{\lambda d!}{n^{d+1}} \sum_{i\geq 0}(\frac{j}{n})^i {d+i \choose i} =nd+1λd!​i≥0∑​(nj​)i(id+i​)
= λ d ! n d + 1 ( n n − j ) d + 1 =\frac{\lambda d!}{n^{d+1}} (\frac{n}{n-j})^{d+1} =nd+1λd!​(n−jn​)d+1
最后还剩下一个问题,如果对于每个 a i a_i ai​我们都暴力做dp来求 λ \lambda λ,令 m = m a x { a i } m=max\{a_i\} m=max{ai​}复杂度就是 O ( n 4 m 2 ) O(n^4 m^2) O(n4m2),会TLE
正确姿势是一开始求出 ∏ i ( e x − G i ( x ) ) \prod_{i}(e^x-G_i(x)) ∏i​(ex−Gi​(x)),对于每个 a i a_i ai​再消除它
复杂度 O ( n 3 m 2 ) O(n^3m^2) O(n3m2)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<assert.h>
#define fo(i,a,b) for(int i=(a);i<=(b);++i)
#define fd(i,b,a) for(int i=(b);i>=(a);--i)
using namespace std;
typedef long long ll;
int read(){int n=0,p=1;char ch;for(ch=getchar();ch<'0' || ch>'9';ch=getchar())if(ch=='-') p=-1;for(;'0'<=ch && ch<='9';ch=getchar()) n=n*10+ch-'0';return n*p;}
const int N=33,mo=998244353;
void inc(int &x,int y){x=(x+y)%mo;}
int qmi(int x,int n)
{int t=1;for(x%=mo;n;n>>=1,x=1ll*x*x%mo) if(n&1) t=1ll*t*x%mo;return t;
}
int n,m,a[N],f[N][N][N*N],g[N][N*N],fac[N*N],ifac[N*N],inv[N*N];
int main()
{n=read();fo(i,1,n) a[i]=read(),m=max(m,a[i]);fac[0]=ifac[0]=inv[1]=1;fo(i,1,n*m) fac[i]=1ll*fac[i-1]*i%mo;ifac[n*m]=qmi(fac[n*m],mo-2);fd(i,n*m-1,1) ifac[i]=1ll*ifac[i+1]*(i+1)%mo,inv[i+1]=1ll*ifac[i+1]*fac[i]%mo;f[0][0][0]=1;fo(i,1,n)fo(j,0,i)fo(k,0,i*m){if(j) inc(f[i][j][k],f[i-1][j-1][k]);fo(l,0,min(a[i]-1,k))inc(f[i][j][k],-1ll*f[i-1][j][k-l]*ifac[l]%mo);}fo(i,1,n){memset(g,0,sizeof(g));fd(j,n-1,0)fo(k,0,(n-1)*m){g[j][k]=f[n][j+1][k];fo(l,0,min(a[i]-1,k))inc(g[j][k],1ll*g[j+1][k-l]*ifac[l]%mo);}int ans=0;fo(j,0,n-1)fo(k,0,(n-1)*m) if(g[j][k]){int lamda=1ll*ifac[a[i]-1]*g[j][k]%mo,d=(a[i]-1)+k;int t=1ll*lamda*qmi(inv[n-j],d+1)%mo*fac[d]%mo;ans=(ans+t)%mo;}printf("%d ",(ans%mo+mo)%mo);}return 0;
}

【UOJ #390】【UNR #3】百鸽笼相关推荐

  1. [UNR #3]百鸽笼

    百鸽笼 题解 首先,我们依然可以像上道题一样进行类似的转化. 每次操作时会随机一个使它减小111,我们的目的是当所有数都减到⩽0\leqslant 0⩽0,统计每个数时最后一个见得概率. 我们不妨去尝 ...

  2. [uoj390][UNR #3]百鸽笼【dp】【容斥原理】

    [题目链接] http://uoj.ac/problem/390 [题解] 考虑容斥原理,计算第 i i i列的时候,可以强制一些列在它之后被选取完,其他的列就不用处理了. 那么直到i" r ...

  3. UNR #3 百鸽笼

    题目大意:在UOJ管理员群里一共有\(N\)个管理员,为了容纳这些管理员,vfk准备了\(N+1\)个鸽笼. 为了节省空间,vfk把这些鸽笼堆了起来,共有\(n\)列,第i列放了\(a_i\)个鸽笼, ...

  4. UOJ #390 【UNR #3】百鸽笼 容斥+DP

    题目分析 算法0 每个管理员选哪一列,将构成一个长度为 N − 1 N-1 N−1的序列,序列的种数可以通过经典的将 a a a个相同元素插入到一个没有该元素的长度为 b b b的序列里问题,轻松求出 ...

  5. 【UOJ #390】【UNR #3】百鸽笼(指数型生成函数,二项式定理)

    题面

  6. UOJ.311.[UNR#2]积劳成疾(DP)

    UOJ 序列中的每个位置是等价的.直接令\(f[i][j]\)表示,\(i\)个数的序列,最大值不超过\(j\)的所有序列每个长为\(k\)的子区间最大值的乘积的和. 由\(j-1\)转移到\(j\) ...

  7. JZOJ 5933. 【NOIP2018模拟10.27】百鸽笼

    Description Input 从文件 pigeon.in 中读入数据. 输入第一行包含两个正整数 n, m ,分别表示初始鸽笼数与操作个数. 第二行包含 n 个正整数,第 i 个数表示从左往右第 ...

  8. UOJ #214 [UNR #1]合唱队形 (概率期望计数、DP、Min-Max容斥)

    9个月的心头大恨终于切掉了!!!! 非常好的一道题,不知为何uoj上被点了70个差评. 题目链接: http://uoj.ac/problem/214 题目大意: 请自行阅读. 题解: 官方题解讲得相 ...

  9. 【JZOJ A组】百鸽笼

    Description Input 从文件 pigeon.in 中读入数据. 输入第一行包含两个正整数 n, m ,分别表示初始鸽笼数与操作个数. 第二行包含 n 个正整数,第 i 个数表示从左往右第 ...

最新文章

  1. 开源软件与商业软件的选择
  2. 六大策略迎接数据中心巨大变革
  3. CSS学习17之动画
  4. 怎么在VS监视DataSet类型的数据
  5. 一家贩卖8亿份个人简历的公司 现已人去楼空
  6. 基于vue(element ui) + ssm + shiro 的权限框架
  7. Lesson 02amp;03 for Plotting in R for Biologists
  8. ca蜘蛛特效nvas-nest.js | Bootstrap中文网开源项目免费 CDN 服务
  9. 单片机C语言字符串转数字
  10. iOS测试——ios未受信任的企业级开发者怎么解决?
  11. 修复Ubuntu系统安装steam无法打开
  12. MAC word2015 插入罗马字母
  13. 上线时的相关检查清单
  14. 分布式事务CAP理论
  15. 整理一些个人常用的windows软件
  16. 大数据开发薪资水平怎么样?
  17. Postgresql通过docker进行高可用部署 pgpool-II
  18. minicom的按键控制_minicom使用教程
  19. 2020京东春招笔试题目
  20. 计算机组成原理-入门篇-01冯·诺依曼体系结构

热门文章

  1. 方舟自建服务器500人,明日方舟台服追赶进度引发炎上 限时掉落重叠 官方补偿500理智...
  2. MATLAB 数学应用 线性代数 判断矩阵是否为对称正定矩阵
  3. mapperbytebuffer.java,深入浅出MappedByteBuffer
  4. 微信小程序从入门到精通
  5. 学透JSON.stringify
  6. Python:善用query,从excel数据中批量提取数据到新文件
  7. bs4获取html文档,使用bs4提取html文件中的文本
  8. 如何查看电脑是多少位系统?
  9. MySQL中的IFNULL函数和IF函数
  10. MOV AX ,OFFSET[DI+10H]的错误