子曰.“古者言之不出,
耻躬之不逮也。”
孔子说:“君子从不轻易地发表言论,他们以说了而做不到为可耻。
摘要:本文从组合数学的角度,引用代数系统的知识,系统阐述了无重复的组合数和01背包转换。组合数是组合数学中最基础的函数,它是关于子集的枚举,我们会扩展子集的合并。
关键词:组合数学 算法 动态规划
代数系统
最简单的代数系统就是在自然数集中的加法。
如果将一个代数系统看成一个国家/集合,那么A就是这个国家的人,而运算就是道德或者法律构建的关系。
比如说婚姻,劳资,教学的关系。
算两次思想(富比尼原理)
在程序中,相当于改变了循环变量枚举层数。
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
sum+=a[i][j];
}
}
for(int j=1;j<=n;j++)
{
for(int i=1;i<=n;i++)
{
sum+=a[i][j];
}
}
最基础的组合数-无重复组合
帕斯卡恒等式是转移方程的原型。
如果我们是在模系下,求解出组合数。
int qmi(int a,int x)
{
int res=1;
while(x)
{
if(x&1)
(res=a*res)%=mod;
a=(a*a)%mod;
x>>=1;
}
return res;
}
void init()
{
fac[0]=1;
for(int i=1;i<=N;i++)
{
(fac[i]=fac[i-1]*i)%=mod;
}
inv[N]=qmi(fac[N],mod-2);
for(int i=N-1;i>=0;i--)
{
inv[i]=(inv[i+1]*(i+1)%mod);
inv[i]%=mod;
}
}
int C(int n,int m)
{
return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
for(int i=0;i<N;i++)
{
for(int j=0;j<=i;j++)
if(!j)c[i][j]=1;
else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
01背包
我们还是从组合数开始谈起,
有n个物品,背包容量为V,物品的重量为1,物品的价值为1
求出最终选择物品的重量为k的方案数。
有n个物品,背包容量为V,物品的重量为1,物品具有价值v
求出最终背包的重量不超过V的最大价值。
有n个物品,背包容量为V,物品的重量为w,物品具有价值v
求出最终背包的重量不超过V的最大价值。
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= V; j++) {
f[i][j] = f[i - 1][j];
if (j >= w[i])
f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + v[i]);
}
}
引用:
张垚,孔令志编. 数学奥林匹克小丛书 组合数学. 上海:华东师范大学出版社, 2020.04
左孝凌,李为鑑,刘永才编. 离散数学. 上海:上海科学技术文献出版社, 1982.09.
罗勇军,郭卫斌著. 算法竞赛 下. 北京:清华大学出版社, 2022.10.