范德蒙德卷积入门

范德蒙德卷积

范德蒙德卷积(Vandermonde Convolution)是组合数学中的一个重要公式,常用来计算两个组合数的卷积。

定义

给出公式:

\[\sum_{i=0}^{k}\binom{n}{i}\binom{m}{k-i} = \binom{n+m}{k} \]

证明

1.组合意义

先假设这样一个具体情境,有一个长度为 \(n+m\) 的布尔型数组,求出这个数组中有 \(k\)\(1\) 的方案数。

显然,答案是 \(\binom{n+m}{k}\)

但是怎么来推左式呢?

将这个数组分为两个部分,一个是前 \(n\) 个元素,一个是后 \(m\) 个元素

当前面一部分取 \(s\) 个元素,后面一部分取 \(k-s\) 个元素时,根据乘法原理我们可以算出这种情况的答案为 \(\binom{n}{s}\binom{m}{k-s}\)

然后再由加法原理,答案就为 \(\sum_{s=0}^{k}\binom{n}{s}\binom{m}{k-s}\)

2.代数推导

下面给出推导过程,需要使用二项式定理进行展开

\[\begin{aligned} \sum_{r=0}^{n+m}\binom{n+m}{r}x^r &= (x+1)^{n+m}\\ &= (x+1)^n(x+1)^m\\ &= \sum_{p=0}^{n}\binom{n}{p}x^p\sum_{q=0}^{m}\binom{m}{q}x^q\\ &= \sum_{p=0}^{n+m}\sum_{q=0}^{p}\binom{n}{q}\binom{m}{p-q}x^q \end{aligned} \]

应用

[CF785D](Problem - 785D - Codeforces)

经典例题

思路

考虑选择 \(\le p\) 的左括号以及 \(\gt p\) 的右括号的方案数,设 \(p\) 左边的左括号数量为 \(x\) , 右边的右括号的数量为 \(y\)

答案就为

\[\sum_{i=1}^{\min(x,y)}\binom{x}{i}\binom{y}{i}=\binom{x+y}{y} \]

思路就出来了

枚举选择的最右边的左括号的位置,提前处理出左括号前缀和和右括号后缀和,沿用上面的符号,那么方案数就为

\[\sum_{i=0}^{\min(x-1,y-1)}\binom{x-1}{i}\binom{y}{i+1}=\binom{x+y-1}{y-1} \]

由于已经确定了最右边的左括号所以实际可以自由选择的左括号只有 \(x-1\) 个,再预处理一下组合数这道题就解决了

代码

#include <bits/stdc++.h>
#define ll long longusing namespace std;const int N = 2e5+50;
const ll mod = 1e9+7;
int n,pre[N],suf[N];
char s[N];
ll fac[N],infac[N],ans;
inline ll quick_pow(ll x,ll y)
{ll res=1;while(y){if(y&1)res=res*x%mod;x=x*x%mod;y>>=1;}return res;
}
inline ll inv(ll x){return quick_pow(x,mod-2);}
inline void init()
{fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;infac[n]=inv(fac[n]);for(int i=n-1;i>=0;i--)infac[i]=infac[i+1]*(i+1)%mod;
}
inline ll C(int x,int y){return x<y||y<0?0:fac[x]*infac[y]%mod*infac[x-y]%mod;}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>(s+1);n=strlen(s+1);init();for(int i=1;i<=n;i++)pre[i]=pre[i-1]+(s[i]=='(');for(int i=n;i>=1;i--)suf[i]=suf[i+1]+(s[i]==')');for(int i=1;i<=n;i++)if(s[i]=='(')ans=(ans+C(pre[i]+suf[i]-1,suf[i]-1))%mod;cout<<ans<<endl;return 0;
}

[ABC290F](F - Maximum Diameter)

好题,建议读者先思考

思路

由握手定理可知 \(\sum_{i=1}^{n}x_i = 2\times(n-1)\),并且由于图联通所以 \(x_i\) 都为正整数。

先考虑在什么形态下树的直径最长,显然是链

将度数 \(\ge 2\) 的点拿出来构造成一条链,其余的度数为 \(1\) 的点补度数没有满的点,这个时候的直径最长,设度数 $\ge 2 $ 的点的数量为 \(cnt\) 在加上两端度数为 \(1\) 的点,直径为 \(cnt+1\)

枚举度数为 \(1\) 的点,设度为 \(1\) 的点的个数为 \(i\) ,那么剩下没有平的度数就为 \(2\times(n-1)-i\),只需要把这些度数分配给剩余的点。

剩下每个点首先都要分配 \(1\) 的度数,还剩 \(n-2\) 的度数,这是一个经典模型,将 \(n-2\) 分配给剩余的 \(n-i\) 个,并且每个分到的 \(\ge 1\)

考虑插空法,这就相当于在 \(n-2\) 个球中插入 \(n-i-1\) 个空,所以最终的答案就为

\[\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}(n-i+1) \]

但是题目的查询量极大,需要优化,看到两个组合数的特征,容易想到用范德蒙德卷积来优化。

于是原式就可以拆为

\[\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}(n+1)-\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}i=(n+1)\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}-\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}i \]

需要把后面的 \(i\) 给优化掉

这里需要用到等式 \(k\binom{n}{k}=n\binom{n-1}{k-1}\)

只需要把组合数写成阶乘形式就可以证明这个等式

所以原式就可以变为

\[(n+1)\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}-n\sum_{i=2}^{n-1}\binom{n-1}{i-1}\binom{n-2}{n-i-1} \]

再由范德蒙德卷积

\[(n+1)\sum_{i=2}^{n-1}\binom{n}{i}\binom{n-2}{n-i-1}-n\sum_{i=2}^{n-1}\binom{n-1}{i-1}\binom{n-2}{n-i-1}=(n+1)\binom{2n-2}{n-1}-n\binom{2n-3}{n-2} \]

预处理组合数就可以 \(O(1)\) 求出答案

代码

#include <bits/stdc++.h>
#define ll long longusing namespace std;const int N = 2e6+50;
const ll mod = 998244353;
int n;
ll fac[N],infac[N];
inline ll quick_pow(ll x,ll y)
{ll res=1;while(y){if(y&1)res=res*x%mod;x=x*x%mod;y>>=1;}return res;
}
inline ll inv(ll x){return quick_pow(x,mod-2);}
inline void init()
{fac[0]=1;for(int i=1;i<=2000000;i++)fac[i]=fac[i-1]*i%mod;infac[2000000]=inv(fac[2000000]);for(int i=1999999;i>=0;i--)infac[i]=infac[i+1]*(i+1)%mod;
}
inline ll C(ll x,ll y){return fac[x]*infac[y]%mod*infac[x-y]%mod;}
inline void solve()
{cin>>n;cout<<((n+1)*C(2*n-3,n-1)%mod-n*C(2*n-4,n-2)%mod+mod)%mod<<'\n';
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);init();int T;cin>>T;while(T--)solve();return 0;
}

总结

范德蒙德卷积可以将一些计算的复杂度从 \(O(n)\) 降到 \(O(1)\)

主要运用于知道枚举范围并且各个部分枚举总数为定值的式子

有问题可以评论或者私信,对于博客中的不足之处,欢迎指教

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详细介绍:算法题(203):矩阵最小路径和

详细介绍:算法题(203):矩阵最小路径和pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

JAVA中ArrayList主要语法(小白)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

使用jdbcTemplate查询数据库

springboot2版本项目中已经整合了mybatis框架,yml文件中配置好了数据源, 现在想再使用jdbcTemplate查询另外一个数据库,需要怎么配置 # 这是你现有的MyBatis数据源配置(假设使用默认前缀) spring:datasource:url:…

STM32 单片机创建 - I2C 总线

STM32 单片机创建 - I2C 总线2025-09-21 21:55 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important…

线性结构之链表预备知识typedef[基于郝斌课程]

typedef:是c语言的一个关键字,用于给已知数据类型取一个别名 例如typedef unsigned char uint8;此时 uint8 也就是 unsigned char 与define的区别:typedef只可用于对数据类型进行取新名字,define无此限制 typedef由…

Excel滚动表格表头不见了,来回翻动很麻烦,Excel如何固定显示表头?

Windows 系统 冻结首行表头:选中第二行,按下 Ctrl + Shift + F,然后松开按键,再按 F 键,就能冻结首行,让表头始终显示。 冻结首列表头:选中第二列,按下 Ctrl + Shift + F,松开后按 C 键 ,即可冻结首列。 冻结…

asfp导入framework搭建环境

修改大内存,必须要32GB及以上 先关闭正在使用的 swapfile # 查看当前挂载的交换分区/文件 sudo swapon --show# 若显示有 /swapfile,执行以下命令关闭 sudo swapoff /swapfile# 创建新的 swapfile(以 16GB 为例,根…

赛前训练2 连通性问题

以下,斜体表示注意点,粗体表示技巧点。 A spfa 最长路、环具有特殊性质考虑缩点。 容易发现环上的点可以通过跑很多次直到点权全部为 \(0\),于是缩点跑 spfa 最长路即可。实现B 必经边考虑割边,割边考虑边双。 我们…

用 【C# + WinUI3 + 图像动画】 来理解:高数 - 函数 - 初等函数 - 行人-

我记性差,记不住数学公式,希望通过图像化来加深视觉记忆,转化为数学“感觉” “直觉”,在需要的时候,能够 “想到” 类似的场景。通过 C# + WinUI3,对 函数的分类、基本初等函数 进行了学习,图像中眼花缭乱的感…

ansible语句

when判断就是符合条件的话,就可以执行这个模块的内容了默认的when判断,识别变量名,不需要{{}}来引用变量,但是如果是值的话,就需要双引号或者单引号才行vars:name: rhel9when: name # 不需要引号when: "test…

Window 连接 Ubuntu远程桌面

打开Ubuntu远程桌面配置自动登录 编辑 GDM 配置文件(适用于 GNOME 桌面) sudo nano /etc/gdm3/custom.conf [daemon] AutomaticLoginEnable = true AutomaticLogin = 你的用户名 # 替换为实际用户名固定远程密码 创…

代码随想录算法训练营第四天 |24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

24. 两两交换链表中的节点 思路:一次移动两个单位,然后交换两个节点,感觉不难。 注意的点:注意交换节点时候的顺序。/*** Definition for singly-linked list.* type ListNode struct {* Val int* Next *L…

提高杂题

初赛结束了,开始加训复赛。 来自 misaka16172 大手子的推荐。%%% 这里是题单链接:link CF1153E Serval and Snake *2200 交互,思维,二分 首先非常困难的一点就是要注意到当回答为奇数时,说明有恰好一个端点(头尾…

【比赛记录】2025CSP-S模拟赛51

A B C D Sum Rank100 9 54 - 163 11/24A. 算术 列个表格:\(a_i\to\)\(a_j\downarrow\) \(\le0\) \(1\) \(>1\)\(\le0\) ❎ ✅ ✅\(1\) ✅ ✅ ✅\(>1\) ✅ ✅ ❎记录当前 \(=1\)、\(>1\)、\(\ge1\) 的数量即可…

完整教程:【前端面试题✨】Vue篇(一)

完整教程:【前端面试题✨】Vue篇(一)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mo…

Android 源码解析 之 MediaPlayer

Android 源码解析 之 MediaPlayerAndroid 源码解析 之 MediaPlayer 我们可以使用如下工具方法获取视频或者音频时长。 internal fun getDuration(context: Context, uri: Uri): Int {val mediaPlayer: MediaPlayer? =…

STM32初始化串口重定向后printf调试信息不输出的难题

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

算法随笔(一) - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

some

https://www.cnblogs.com/binomial-kimi/p/19104225##666 888 888 888 666 114514