洛谷 P5400 - [CTS2019]随机立方体(组合数学+二项式反演)
二项式反演好题。
首先看到“恰好 \(k\) 个极大值点”,我们可以套路地想到二项式反演,具体来说我们记 \(f_i\) 为钦定 \(i\) 个点为极大值点的方案数,那么
\]
考虑怎么求 \(f_i\),首先我们肯定要选出 \(i\) 个极大的位置。我们假设 \(g_i\) 为选出 \(i\) 个极大的位置的方案数,那么显然 \(g_i\) 就是把每一个位置选择的方案数都乘起来。但这样会算重,具体来说,对于每一个合法的选出 \(i\) 个极大的位置的方案数,我们这样算相当于给全部 \(i\) 个极大点都上了标号,因此一种合法的方案会被重复计算 \(i!\) 次,总方案数还需除以 \(i!\),即
\]
接下来考虑怎么给与这 \(i\) 个极大值点在同一行/列/高度的位置填上数。首先我们设 \(c_i\) 表示与 \(i\) 个极大点在同一行/列/高度的格子数量。显然 \(c_i\) 可以通过总格子数量减去与 \(i\) 个极大值点都不在同一行/列/高度的格子数量,即 \(c_i=nml-(n-i)(m-l)(l-i)\)。再设 \(h_i\) 表示为给与这 \(i\) 个极大值点的任意一个极大值点在同一行/列/高度的位置填上 \(1\sim c_i\) 的数的方案数。我们考虑填上 \(c_i\) 的那个极值点,显然如果去掉那个极值点,那问题就转化为 \(i-1\) 的情况,方案数自然就是 \(h_{i-1}\)。而增加这个极值点则会多出 \(c_i-c_{i-1}\) 个与极大值点在同一行/列/高度的位置,由于第 \(i\) 个极值点已经填好了数,因此我们还需选出 \(c_i-c_{i-1}-1\) 个数,方案数为 \(\dbinom{c_i-1}{c_i-c_{i-1}-1}\),填好这 \(c_i-c_{i-1}-1\) 个数后还可以将它们随意排列,方案数就是 \((c_i-c_{i-1}-1)!\),因此我们可以得到:
\]
即
\]
递推一下有:
\]
最后考虑怎样求 \(f_i\),首先我们钦定 \(i\) 个极大值的位置,方案数 \(g_i\),我们还要选出 \(c_i\) 个数安排给与 \(i\) 个极大值点在同一行/列/高度的点们,方案数 \(\dbinom{nml}{c_i}\),由于 \(i\) 个极值点顺序可以调换,因此还要乘上 \(i!\);剩余 \(nml-c_i\) 个点可以随便填,方案数 \((nml-c_i)!\),最后我们还要将这 \(c_i\) 个数填到对应的位置上去,方案数 \(h_i\),因此
\]
展开来可以得到:
\]
发现有一堆东西可以怼掉,\(i!\) 和 \(\dfrac{1}{i!}\) 怼掉了,\((nml-c_i)!\) 和 \(\dfrac{1}{(nml-c_i)!}\) 怼掉了,我们还可以发现,前面的 \(\dfrac{1}{c_i!}\) 和后面的 \(\prod\limits_{j=1}^i\dfrac{(c_j-1)!}{c_{j-1}!}\) 拼起来变成 \(\dfrac{\prod\limits_{j=1}^i(c_j-1)!}{\prod\limits_{j=1}^ic_j!}\),显然这东西等于 \(\prod\limits_{j=1}^i\dfrac{1}{c_j}\),于是
\]
带到最一开始的答案的式子中
\]
\((nml)!\) 与 \(\dfrac{1}{(nml)!}\) 又怼掉了,剩下的式子中不含我们组合数学中不能直接算的东西(上下底数都很大的组合数、超过 \(10^7\) 的阶乘等),因此预处理出 \(\prod\limits_{j=0}^{i-1}(n-j)(m-j)(l-j)\),以及 \(\prod\limits_{j=1}^i\dfrac{1}{c_j}\),然后直接算上式的值是没问题的。有一个注意点,就是直接对每个 \(c_i\) 算一波逆元复杂度会多个 \(\log\),然后你就会获得 80pts 的好成绩。不过考虑借鉴求阶乘及其逆元的套路,我们先递推求出 \(c_j\) 的前缀积,然后对最后一项求一波逆元,然后再从后往前递推即可求出 \(\dfrac{1}{c_j}\) 的前缀积,这大概也算是组合数学中一个优化的小套路了吧(
复杂度线性。
const int MAXN=5e6;
const int MOD=998244353;
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
int fac[MAXN+5],ifac[MAXN+5];
void init_fac(int n){
for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
int binom(int x,int y){return 1ll*fac[x]*ifac[y]%MOD*ifac[x-y]%MOD;}
int n,m,l,k,g[MAXN+5],pre[MAXN+5],b[MAXN+5],inv_pre[MAXN+5],f[MAXN+5];
int calc(int x){return 1ll*(n-x)*(m-x)%MOD*(l-x)%MOD;}
void solve(){
scanf("%d%d%d%d",&n,&m,&l,&k);b[0]=pre[0]=1;
int lim=min(min(n,m),l),sz=1ll*n*m%MOD*l%MOD,res=0;
for(int i=1;i<=lim;i++) g[i]=(sz-calc(i)+MOD)%MOD;
for(int i=1;i<=lim;i++) pre[i]=1ll*pre[i-1]*g[i]%MOD;
inv_pre[lim]=qpow(pre[lim],MOD-2);
for(int i=lim-1;~i;i--) inv_pre[i]=1ll*inv_pre[i+1]*g[i+1]%MOD;
for(int i=1;i<=lim;i++) b[i]=1ll*b[i-1]*calc(i-1)%MOD;
for(int i=1;i<=lim;i++) f[i]=1ll*b[i]*inv_pre[i]%MOD;
for(int i=k;i<=lim;i++){
int mul=1ll*binom(i,k)*f[i]%MOD;
if((i-k)&1) res=(res-mul+MOD)%MOD;
else (res+=mul)%=MOD;
} printf("%d\n",res);
}
int main(){
init_fac(MAXN);
int qu;scanf("%d",&qu);while(qu--) solve();
return 0;
}
洛谷 P5400 - [CTS2019]随机立方体(组合数学+二项式反演)的更多相关文章
- 洛谷 P5401 - [CTS2019]珍珠(NTT+二项式反演)
题面传送门 一道多项式的 hot tea 首先考虑将题目的限制翻译成人话,我们记 \(c_i\) 为 \(i\) 的出现次数,那么题目的限制等价于 \(\sum\limits_{i=1}^D\lflo ...
- 【题解】Luogu P5400 [CTS2019]随机立方体
原题传送门 毒瘤计数题 我们设\(dp_i\)表示至少有\(i\)个极大数字的概率,\(ans_i\)表示恰好有\(i\)个极大数的概率,\(mi=Min(n,m,l)\) 易知: \[dp_i=\s ...
- 【BZOJ2830/洛谷3830】随机树(动态规划)
[BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...
- LOJ 3119: 洛谷 P5400: 「CTS2019 | CTSC2019」随机立方体
题目传送门:LOJ #3119. 题意简述: 题目说的很清楚了. 题解: 记恰好有 \(i\) 个极大的数的方案数为 \(\mathrm{cnt}[i]\),则答案为 \(\displaystyle\ ...
- [LOJ3119][CTS2019|CTSC2019]随机立方体:组合数学+二项式反演
分析 感觉这道题的计数方法好厉害.. 一个直观的思路是,把题目转化为求至少有\(k\)个极大的数的概率. 考虑这样一个事实,如果钦定\((1,1,1),(2,2,2),...,(k,k,k)\)是那\ ...
- LOJ3119 CTS2019 随机立方体 概率、容斥、二项式反演
传送门 为了方便我们设\(N\)是\(N,M,L\)中的最小值,某一个位置\((x,y,z)\)所控制的位置为集合\(\{(a,b,c) \mid a = x \text{或} b = y \text ...
- 题解-CTS2019随机立方体
problem \(\mathtt {loj-3119}\) 题意概要:一个 \(n\times m\times l\) 的立方体,立方体中每个格子上都有一个数,如果某个格子上的数比三维坐标中至少有一 ...
- 洛谷P3158 [CQOI2011]放棋子 组合数学+DP
题意:在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同颜色的棋子不能在同一行或者同一列.有多少祌方法? 解法:这道题不会做,太菜了qwq.题解是看洛谷大佬的. 设C是组合数, ...
- 洛谷P2568 GCD (欧拉函数/莫比乌斯反演)
P2568 GCD 题目描述 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 输入输出格式 输入格式: 一个整数N 输出格式: 答案 输入输出样例 输入 ...
随机推荐
- 小甲鱼零基础学python第25讲课后习题动手练习--通讯录
小甲鱼零基础学python第25讲课后习题动手练习---通讯录 **************************通讯录要求******************************* 输入指令: ...
- java的加载与执行原理剖析
到目前为止,我们接触过的重点术语,总结一下: Java体系的技术被划分为三大块: JavaSE:标准版 JavaEE:企业版 JavaME:微型版 安装JDK之后: JDK:java开发工具箱 JRE ...
- 【UE4 C++】调用外部链接库 lib静态库
简述 本例以插件形式测试 使用Lib引用,打包程序运行不用再拷贝lib文件 需要 lib 文件和 .h 头文件 lib部分的代码 .h 头文件 #pragma once #ifndef __MYTES ...
- 【c++ Prime 学习笔记】第11章 关联容器
关联容器的元素按照关键字来保存和访问,而顺序容器的元素是按照在容器中的位置来保存和访问 关联容器支持高效的关键字查找和访问 2种关联容器: map中的元素是关键字-值对(key-value对),关键字 ...
- 如何获取ISO8601定义的Work Week
工作中遇到一个需求,需要在打印标签的时候打印生产当天的工作周.工作周按照ISO-8601定义的标准计算.找到两种方案. Excel函数 C#代码 Excel函数 非常简单,调用一个Excel自带函数就 ...
- [对对子队]会议记录4.14(Scrum Meeting 5)
今天已完成的工作 刘子航 工作内容:设计第2,3关 相关issue:设计关卡2,3 吴昭邦 工作内容:制作场景,暂时解决了坐标错位问题 相关issue:实现游戏场景中的必要模型 何瑞 ...
- linux ar
转载:Linux ar命令 | 菜鸟教程 (runoob.com) Linux ar命令用于建立或修改备存文件,或是从备存文件中抽取文件. ar可让您集合许多文件,成为单一的备存文件.在备存文件中,所 ...
- uni-app(Vue)中(picker)用联动(关联)选择以至于完成某些功能
如下图所示,在项目中需求是通过首先选择学生的专业,选好之后在每个专业下面选择对应的学期,每个学期有对应的学费,因此就需要联动选择来实现这一功能. 以下仅展示此功能主要代码: <div class ...
- Spring一套全通4—持久层整合
百知教育 - Spring系列课程 - 持久层整合 第一章.持久层整合 1.Spring框架为什么要与持久层技术进行整合 1. JavaEE开发需要持久层进行数据库的访问操作. 2. JDBC Hib ...
- 【java+selenium3】模态框处理(五)
一.模态框的定义: 模态对话框(Modal Dialogue Box , 又叫做模式对话框),是指在用户想要对话框以外的应用程序进行操作时候,必须先对该对话框进行响应.如单击[确定]或者[返回]按钮等 ...