8.14.10 ACM-ICPC 组合数学 伯努利数

8.14.10 ACM-ICPC 组合数学 伯努利数

组合数学中的伯努利数

在组合数学中,伯努利数(Bernoulli Numbers)是一类重要的数列,它们在数论、微积分和其他数学分支中有广泛的应用。特别是在 ACM-ICPC 编程竞赛中,伯努利数常用于求解一些复杂的数学问题。本节将介绍伯努利数的定义、性质以及在编程竞赛中的应用。

一、伯努利数的定义

伯努利数 BnB_nBn​ 是通过下面的递推公式定义的:

其中 (n+1k)\binom{n+1}{k}(kn+1​) 是二项式系数。

二、伯努利数的性质

  1. 奇次伯努利数:除了 B1B_1B1​ 之外,所有奇次伯努利数都是零,即 B
  2. 生成函数:伯努利数的生成函数为:
  3. 递推关系:根据递推公式,可以逐项计算伯努利数。例如:

三、伯努利数在编程竞赛中的应用

在 ACM-ICPC 编程竞赛中,伯努利数可以用于解决多种复杂的数学问题。以下是一些典型应用:

1. 高次求和

伯努利数常用于高次求和公式。例如,求 ∑k=1nkm\sum_{k=1}^{n} k^m∑k=1n​km 可以通过伯努利多项式来简化。公式为:

2. 欧拉-麦克劳林公式

伯努利数在欧拉-麦克劳林求和公式中也有重要应用,用于将离散求和转换为积分形式,简化计算:

3. 组合计数问题

在组合数学中,伯努利数用于解决一些计数问题,如计算 Stirling 数和 Bell 数。

四、编程实现

以下是伯努利数的简单递归计算方法:

#include <iostream>
#include <vector>

using namespace std;

const int MAXN = 100;
vector<double> bernoulli(MAXN + 1);

void compute_bernoulli() {
    bernoulli[0] = 1.0;
    for (int m = 1; m <= MAXN; ++m) {
        bernoulli[m] = 0.0;
        for (int k = 0; k < m; ++k) {
            bernoulli[m] += (bernoulli[k] / (m - k + 1)) * (m + 1);
        }
        bernoulli[m] = 1.0 - bernoulli[m];
    }
}

int main() {
    compute_bernoulli();
    for (int i = 0; i <= 10; ++i) {
        cout << "B_" << i << " = " << bernoulli[i] << endl;
    }
    return 0;
}

总结

伯努利数在组合数学中具有重要地位,其广泛应用于数论、高次求和、欧拉-麦克劳林公式以及组合计数问题中。掌握伯努利数的性质和计算方法,对于解决 ACM-ICPC 编程竞赛中的复杂数学问题具有重要意义。通过以上内容的学习和代码实现,读者可以更好地理解和应用伯努利数。


二、等幂求和

伯努利数是由雅各布·伯努利在研究 mmm 次幂和的公式时发现的。我们记:

伯努利观察了如下一列公式,勾画出一种模式:

三、递推公式

伯努利数的递推公式如下:

伯努利数由隐含的递推关系定义:

四、伯努利数的性质

  1. 奇次伯努利数:除了 B1B_1B1​ 之外,所有奇次伯努利数都是零,即 B2k+1=0B_{2k+1} = 0B2k+1​=0(对于 k≥1k \geq 1k≥1)。
  2. 生成函数:伯努利数的生成函数为: xex−1=∑n=0∞Bnxnn!\frac{x}{e^x - 1} = \sum_{n=0}^{\infty} B_n \frac{x^n}{n!}ex−1x​=∑n=0∞​Bn​n!xn​
  3. 递推关系:根据递推公式,可以逐项计算伯努利数。例如: B2=16,B4=−130,B6=142,等等B_2 = \frac{1}{6}, \quad B_4 = -\frac{1}{30}, \quad B_6 = \frac{1}{42}, \quad \text{等等}B2​=61​,B4​=−301​,B6​=421​,等等

五、证明伯努利数的递推关系

利用归纳法可以证明伯努利数的递推关系。这个证明方法来自《Concrete Mathematics》。

通过二项式系数的恒等变换和归纳法,可以得到以下公式:

将原式中两边都减去 Sm+1(n)S_{m+1}(n)Sm+1​(n) 后可以得到:

不妨设 Δ=Sm(n)−S^m(n)\Delta = S_m(n) - \hat{S}_m(n)Δ=Sm​(n)−S^m​(n),并且将 S^j(n)\hat{S}_j(n)S^j​(n) 展开,那么有:

将第二个求和顺序改为逆向,再将组合数的写法恒等变换可以得到:

对两个求和符号进行交换,可以得到:

对 (m+1j)(jk)\binom{m+1}{j}\binom{j}{k}(jm+1​)(kj​) 进行恒等变换:

那么式子就变成了:

考虑我们前面提到过的递归关系:

代入后可以得到:

于是 Δ=0\Delta = 0Δ=0,且有 Sm(n)=S^m(n)S_m(n) = \hat{S}_m(n)Sm​(n)=S^m​(n)。

六、利用指数生成函数证明

对递推式:

两边都加上 Bm+1B_{m+1}Bm+1​,即得到:

设 B(z)=∑i≥0Bii!ziB(z) = \sum_{i \ge 0}\frac{B_i}{i!}z^iB(z)=∑i≥0​i!Bi​​zi,注意到左边为卷积形式,故:

调换求和顺序:

代入 B(z)=zez−1B(z) = \frac{z}{e^z - 1}B(z)=ez−1z​:

故得证。

七、参考实现

以下是伯努利数的参考实现代码:

typedef long long ll;
const int maxn = 10000;
const int mod = 1e9 + 7;
ll B[maxn];        // 伯努利数
ll C[maxn][maxn];  // 组合数
ll inv[maxn];      // 逆元(计算伯努利数)

void init() {
    // 预处理组合数
    for (int i = 0; i < maxn; i++) {
        C[i][0] = C[i][i] = 1;
        for (int k = 1; k < i; k++) {
            C[i][k] = (C[i - 1][k] % mod + C[i - 1][k - 1] % mod) % mod;
        }
    }
    // 预处理逆元
    inv[1] = 1;
    for (int i = 2; i < maxn; i++) {
        inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    }
    // 预处理伯努利数
    B[0] = 1;
    for (int i = 1; i < maxn; i++) {
        ll ans = 0;
        if (i == maxn - 1) break;
        for (int k = 0; k < i; k++) {
            ans += C[i + 1][k] * B[k];
            ans %= mod;
        }
        ans = (ans * (-inv[i + 1]) % mod + mod) % mod;
        B[i] = ans;
    }
}

总结

伯努利数在组合数学中占有重要地位,其应用范围包括高次求和、欧拉-麦克劳林公式、组合计数等。掌握伯努利数的定义、性质和计算方法,对于解决 ACM-ICPC 编程竞赛中的复杂数学问题具有重要意义。通过本文的学习和代码实现,读者可以更好地理解和应用伯努利数。

  • 37
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值