废稿站
lgp10596集合选数
做法解析
二项式反演初步
在讲这题之前,先较为详细地讲解一下二项式反演。
反演是什么?可以这么理解:对于两个数列 \(f(x),g(x)\) 而言,若它们之间存在某种对应关系,使得不仅能从 \(f(x)\) 推出 \(g(x)\),还能从 \(g(x)\) 反推出 \(f(x)\),那么这个过程就叫做反演。
形式化地,称 \(f(n)\) 为原数列,\(g(n)\) 为新数列,并满足 \(f(n)=\sum_{i=0}^{n}a_{n,i}\times g(i)\),那么反演就是我们通过 \(g(n)\) 求 \(f(n)\),即计算 \(g(n)=\sum_{i=0}^{n}b_{n,i}\times f(i)\)。
二项式反演的一个基础形式是:若 \(g(n)=\sum_{i=m}^n\binom{n}{i}f(i)\),则 \(f(n)=\sum_{i=m}^{n}(-1)^{n-i}\binom{n}{i}g(i)\)。这个式子在代数意义上的正确性是无需多言的。
证明上式的步骤:先把 \(g(i)\) 用 \(f(j)\) 表示。把 \(\binom{n}{i}\binom{i}{j}\) 改写成 \(\binom{n}{j}\binom{n-j}{n-i}\)。再交换一波求和符号后,你发现最后那个 \(\sum_{i=j}^n(-1)^{n-i}\binom{n-j}{n-i}\) 实际上等于 \([n=j]\)(二项式定理推论)。这样就证明完了。
这个东西是干什么用的呢?意义在于我们可以给它赋予对应的组合意义。
注:实际上,能用 \(f(n)\) 和 \(g(n)\) 表示的东西都仅以 \(n\) 为自变量。这说明你计数的东西差不多是需要满足元素之间互相等价的。
-
记 \(f(n)\) 为大小为 \(n\) 的方案中 \(n\) 个元素恰全部满足某个条件的方案数,\(g(n)\) 是 \(n\) 个元素中至少有 \(m\) 个元素满足某条件的方案数。则显然有:\(g(n)=\sum_{i=m}^n\binom{n}{i}f(i)\)。
-
类似地,还有:\(g(k)=\sum_{i=k}^n\binom{i}{k}f(i)\Leftrightarrow f(k)=\sum_{i=k}^n(-1)^{i-k}\binom{i}{k}g(i)\)。这里 \(f(k)\) 可表示大小为 \(k\) 的方案中恰好 \(k\) 个元素满足某条件的方案数,而 \(g(k)\) 可表示“大小若干的方案中至少 \(k\) 个元素满足某条件”(其中钦定与否视作不同方案)的方案数。
那么你在知道 \(g(n)\) 的时候就可以用反演把 \(f(n)\) 淦出来了。
就这题而言
这个题的条件看起来就可以用二项式反演干掉。你设 \(f(k)\) 为交集恰好为 \(k\) 的方案数,\(g(k)\) 为钦定交集至少为 \(k\),其它随意(计数区分钦定与否)的方案数。那么显然满足:\(g(k)=\sum_{i=k}^n\binom{i}{k}f(i)\)。
\(g(k)\) 也是好求的,先钦定某 \(k\) 个(系数 \(\binom{n}{m}\))元素满足条件,剩下 \(n-m\) 个元素可以(在都包含钦定元素的基础上)形成 \(2^{n-m}\) 个集合,你的选法抛掉“一个都不选”就是 \(2^{2^{n-m}}-1\)。
事已至此,你反演罢。
对唐诗问题的解答
为什么答案不是 \(g(k)-g(k+1)\)?“至少为 \(k+1\)”减去“至少为 \(k\)”那不就是“恰好为 \(k\)”吗?
我们来代数推导一波这东西等于什么。
显然后面那坨东西不必然是 \(0\) 吧。
但组合意义上呢?
实际上你从上式的最终结果就能看出来端倪。\(\binom{i}{k}\) 代表着我们从 \(i\) 个里面钦定 \(k\) 个,后者亦然。我们的 \(g(i)\) 是区分元素钦定与否的。钦定元素的数量都不一样,怎么可能完全消掉呢?
所以另一方面来说,“钦定”也不能简单和“至少”划等号。
lgp8476的线段树二分原型机
int binaser(int p,int l,int r,int x,int y,lolo val){
if(l==r)return mn[p]>=val?l:-1;
int mid=(l+r)>>1,res=-1;pushdown(p,l,mid);
if(x<=l&&r<=y){
if(mn[ls(p)]>val)return l;
if(mn[ls(p)]<=val&&mn[rs(p)]>val){
res=binaser(ls(p),l,mid,x,y,val);
return res==-1?mid+1:res;
}
if(mn[rs(p)]<=val)return binaser(rs(p),mid+1,r,x,y,val);
return -1;
}
if(x<=mid)res=binaser(ls(p),l,mid,x,y,val);
if(res==-1&&y>mid)res=binaser(rs(p),mid+1,r,x,y,val);
return res;
}
关于求强连通分量时的tarjan中代码与求双连通分量时的代码统一而导致的low值定义问题
这个low数组与其说是记录【最早】时间戳不如说是相比于当前【更早】时间戳吧,然后判断强连通分量的时候只需要判断low和dfn数组值不同也就是不为根就行了。
突然悟了,确实,出栈是一直出道dfni == lowi才停止出栈,这样一个强联通分量就OK了,low按照dfn判断的话确实不一定会是最早的,因该是比当前点早的
双连通分量
有一个性质是,对于一个无向图的 \(\texttt{DFS}\) 生成树,其只有树边和返祖边。
LGP10221 [UPTS 2024] 重塑时光 学习笔记
前言
省选打的太拉了,遂回来补图计数——
当我在考场上看到岁月时,我意识到那是个显然到不能再显然的状压图计数 DP。
脑海里浮现出来从来没搞懂过的重塑时光和主旋律,我却放弃了拿分的想法:因为我的推箱子还只会 A 和 B 两个性质——直到考试结束我也不确信那是个 DS,就算是,我也不太确信我能稳拿一个不那么板的线段树。
赛后不仅发现那题人均切掉,还发现 B 性质甚至莫名其妙挂了,属实幽默完了。
我重塑你的 move!
过掉这道题,真的能重塑时光吗?
题意简述
小 \(\text{T}\) 有一条时间线,上面有 \(n\) 个事件(\(1\sim n\) 共 \(n\) 个数)。邪恶生物小 \(\text{S}\) 将其随机打乱为一个排列 \(P\),并且进行 \(k\) 次操作,每次操作会往序列里任何两个元素(原排列中的元素、之前插入的剪断点)间隔中插入一个剪断点。最后,小 \(\text{S}\) 会在每个剪断点处把序列剪开,将排列 \(P\) 分割成 \((k+1)\) 段(可能为空的)序列。
现在小 \(\text{T}\) 想要拯救这条时间线,他准备把这 \((k+1)\) 段序列重排一下。不过事件之间有一些逻辑关系,存在 \(m\) 条先后顺序要求 \((u,v)\),要求事件 \(u\) 的发生时间必须在事件 \(v\) 之前。
请帮小 \(\text{T}\) 计算有多大的概率,对于小 \(\text{S}\) 操作后的结果存在合法的重排方案。
做法解析
既然是算概率,我们先考虑下总方案数如何——发现它是个简单且有限的数:\((n+k)!\)。所以我们可以把题目转化为算方案数,最后除以 \((n+k)!\) 即可。
然后呢?\(n\le 15\),限制又形如“\(u\) 必须在 \(v\) 前”这样,我们自然联想到把问题搬上图论,让 \(u\) 往 \(v\) 连一条有向边。这样,一种操作结果可以成功重排,当且仅当每个段内顺序都符合 DAG 序,将每个段缩成一个大点后也可以得到一张 DAG。“段内有序”太烦人了,我们尝试预处理出每个点集的合法重排方案。
这个时候的复杂度是 \(O(n^2 3^n)\) 的,听说常熟小的代码可能已经可以屮过去了,然而我的代码似乎不行(submission)。
观察到 \(f\) 的转移很像个多项式,没准我们可以借由此拿掉一个 \(n\)。
代码实现
反思总结
发现总方案数有限的时候可以选择把概率鲨了转成方案数。
看到多项式乘法状物的转移可以想想拉插优化。
浙公网安备 33010602011771号