经过一天的学习,我们发现伯努利数是个非常有用 (个屁) 的数列
定义
但是...伯努利数是什么呢?我们先给伯努利数一个定义:
令 B(i) 表示 伯努利数第 i 项,那么有:
n∑i=0(n+1i)Bi=0, n>0
当然 B0=1 ,于是上面的式子就可以一直推下去了...
暴力计算
我们按照上面的式子可以算出:
B0=1,B1=−12,B2=16,B3=0,B4=130······
但是这样的效率嘛 【滑稽
当然是 n2 的啦~ 于是我们试图寻找更高效的办法...
高效计算
我们发现,根据定义有这么个等式:
n∑i=0(ni)Bi=Bn,n>1
这里原本 n 是 n+1 的,为了方便我们把 n 带进去...
然后这个式子有什么用呢?当然有用咯~ 这玩意儿可是能化成卷积的形式丫!
于是拆个组合数玩玩,看这里:
n∑i=0Bii!(n−i)!=Bnn!,n>1
我们发现 n=0 时,其实也满足上面的式子,只要我们定义 0!=1
n∑i=0Bii!1(n−i)!=Bnn!,n≠1
∞∑n=0,n≠1n∑i=0Bii! ·1(n−i)!=∞∑n=0,n≠1Bnn!
注意上面的 n 仍然不等于 1 ...
然后我们是不是发现这玩意儿左边其实是...卷积呢!1i! 不就是每项系数为 1 的多项式指数函数?
我们把伯努利数除去阶乘当做是一个多项式的系数,那么原来的式子就可以搞生成函数了!
但我们首先还要把 n=1 的情况加进去:
∞∑n=0,n≠1n∑i=0Bii! ·1(n−i)!=∞∑n=0,n≠1Bnn!
∞∑n=0n∑i=0Bii! ·1(n−i)!=∞∑n=0Bnn!+[n=1]
你问我为什么这么写?暴力算一下 n=1 的情况不就发现两边差了多少嘛!
然后转个多项式我们就可以开始生成函数了 QVQ
∞∑n=0(n∑i=0Bii! ·1(n−i)!)xn=∞∑n=0(Bnn!+[n=1])xn
∞∑n=0n∑i=0Bii!xi ·1(n−i)!xn−i=∞∑n=0(Bnn!+[n=1])xn
B(x)ex=B(x)+x
这里之所以加了 x 是因为上面的 x1 系数多了个 1
然后我们继续推式子:
B(x)=xex−1
B(x)=(ex−1x)′
也就是说,我们只要阶乘算出来整体左移一位然后求个逆就好了
但是这里要注意的是,我们这样求出的是指数型生成函数的伯努利数的多项式,真正的伯努利数列要在我们求出来这个多项式系数的基础上乘上对应的阶乘(也就是在指数型生成函数的多项式中除去的那个阶乘)
code
代码如下...丑的一比...而且还省去了求逆的具体函数...
- inline void prep(int len){
- B[0]=ifac[0]=ifac[1]=fac[0]=fac[1]=1;
- fp(i,2,len) ifac[i]=mul(mod-mod/i,ifac[mod%i]);
- fp(i,2,len) ifac[i]=mul(ifac[i-1],ifac[i]);
- fp(i,2,len) fac[i]=mul(fac[i-1],i);
- get_inv(ifac+1,B,len);
- fp(i,2,len) B[i]=mul(B[i],fac[i]);
- }
补充
伯努利数其实分两类: B+ 和 B− ,我们上面讨论的是 B− ,这两者...唯一的区别就是 B1 一个是正的一个是负的,具体而言,对于伯努利数列的每一项有: $B_i^+ = (-1)^i B_i^- $ ,但由于伯努利数列的奇数项 B2n+1 在 n>1 的情况下都是等于 0 的,所以两个数列唯一不同的就是 B1 这一项了
那么我们重新写一遍伯努利数列就是:
B0=1,B±1=±12,B2=16,B3=0,B4=130······
那么另一种不大常见的 B+ 有什么用么?或者说什么特殊的性质?
当然是有的咯,对于下面要说的 S(n,k) 这个幂和函数,如果 S(n,k) 是这么定义的:
S(n,k)=n∑i=0ik
那么令 Bi 表示伯努利数列 B+ 的第 i 项,则有:
S(n,k)=1k+1k∑i=0(k+1i)Bink+1−i
好像并没有什么软用...但是有时候要用到的话可能会让你的推出来的式子更加简洁?【雾
模板
然后这里是板子题:
n2 暴力足以优雅水过~
要用任意MTT哟~
题解点这里
应用
伯努利数有个非常良好 (个屁) 的性质:
令:
S(n,k)=n−1∑i=1ik
则:
S(n,k)=1k+1k∑i=0(k+1i)Bink+1−i
即:
PS:关于上面等式的证明可以看这里
然后一系列推倒:
这可不就是卷积的形式嘛!
现在我们就可以在一些 (dl)数学题里面大展拳脚了呢~
比如这道:
题解点这里