求解自然数幂和的n种方法

问题的引入

给定n,kn,kn,k∑i=1nik\sum_{i=1}^ni^ki=1nik

1. 循环

四年级应该会循环了。

能做到O(nk)O(nk)O(nk)的优秀时间复杂度。

2. 快速幂

五年级学了快速幂之后就能做到O(nlog2k)O(nlog_2k)O(nlog2k)

请不要小看这个算法。有时候在特定的情况下(例如nnn很小,或1→n1\rightarrow n1n的距离变得很小时),这个复杂度真的很优秀。

3. 差分法

六年级应该知道差分和二项式定理了。那么:(a+1)k−ak=∑i=0k−1Ckiai(a+1)^k-a^k=\sum_{i=0}^{k-1}C_k^ia^i(a+1)kak=i=0k1Ckiai

于是:
(n+1)k−1=∑i=1n(i+1)k−ik                =∑i=1n∑j=0k−1Ckjij                  =∑i=0k−1Cki∑j=1nji              =∑i=0k−1CkiS(i) (n+1)^k-1 =\sum_{i=1}^n (i+1)^k-i^k \\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\sum_{i=1}^n\sum_{j=0}^{k-1}C_k^ji^j\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\sum_{i=0}^{k-1}C_k^i\sum_{j=1}^n j^i\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\sum_{i=0}^{k-1}C_k^i S(i) (n+1)k1=i=1n(i+1)kik                =i=1nj=0k1Ckjij                  =i=0k1Ckij=1nji              =i=0k1CkiS(i)∴(n+1)k+1−1=∑i=0kCk+1iS(i)\therefore (n+1)^{k+1}-1=\sum_{i=0}^kC_{k+1}^iS(i)(n+1)k+11=i=0kCk+1iS(i)

i=ki=ki=k时移项,可以得到(k+1)S(k)=(n+1)k+1−1−∑i=0k−1Ck+1iS(i)(k+1)S(k)=(n+1)^{k+1}-1-\sum_{i=0}^{k-1}C_{k+1}^iS(i)(k+1)S(k)=(n+1)k+11i=0k1Ck+1iS(i)

所以S(k)=(n+1)k+1−1−∑i=0k−1Ck+1iS(i)k+1S(k)=\frac{(n+1)^{k+1}-1-\sum_{i=0}^{k-1}C_{k+1}^iS(i)}{k+1}S(k)=k+1(n+1)k+11i=0k1Ck+1iS(i)

同时仔细观察这个式子,我们发现,kkk次方和的求和公式是k+1k+1k+1次的。归纳证明即可。

3. 倍增

初一应该会倍增了,所以我们令fn,k=∑i=1nikf_{n,k}=\sum_{i=1}^ni^kfn,k=i=1nik

nnn是奇数的时候直接由fn−1,k+nkf_{n-1,k}+n^kfn1,k+nk转移过来。偶数的时候拆开来,运用简单的二项式定理,一波式子推得:f(n,k)=f(n2,k)+∑j=0kCkj∗f(n2,j)∗n2k−jf(n,k)=f(\frac{n}{2},k)+\sum_{j=0}^kC_k^j*f(\frac{n}{2},j)*\frac{n}{2}^{k-j}f(n,k)=f(2n,k)+j=0kCkjf(2n,j)2nkj

每一层的fn,kf_{n,k}fn,k我们计算的时间复杂度都是O(k2)O(k^2)O(k2)的,lognlog_nlogn层,时间复杂度O(k2logn)O(k^2log_n)O(k2logn).

4. 高斯消元

初一应该会高斯消元了。这是个大脑洞。虽然时间复杂度比上一个还劣一些。

根据kkk次方和的求和公式是k+1k+1k+1次的,所以列出k+2k+2k+2条式子就可以唯一确定这个多项式。

时间复杂度O(k3)O(k^3)O(k3).

5. 第一类斯特林数

初二来学习一下斯特林数。

第一类斯特林数我们一般清楚的是它的组合意义,即把nnn个元素分成kkk个圆排列的方案。根据组合意义,我们不难推出它的式子是Su(n,m)=Su(n−1,m−1)+(n−1)Su(n−1,m)S_u(n,m)=S_u(n-1,m-1)+(n-1)S_u(n-1,m)Su(n,m)=Su(n1,m1)+(n1)Su(n1,m)

但事实上,我们求解自然数幂和需要用到的是它的原始定义
xn↓=x⋅(x−1)⋅(x−2)⋯(x−n+1)=∑k=0nss(n,k)⋅xkx^{n\downarrow}=x\cdot (x-1)\cdot (x-2)\cdots (x-n+1)=\sum_{k=0}^ns_s(n,k)\cdot x^kxn=x(x1)(x2)(xn+1)=k=0nss(n,k)xkxn↑=x⋅(x+1)⋅(x+2)⋯(x+n−1)=∑k=0nsu(n,k)⋅xkx^{n\uparrow}=x\cdot (x+1)\cdot (x+2)\cdots(x+n-1)=\sum_{k=0}^ns_u(n,k)\cdot x^kxn=x(x+1)(x+2)(x+n1)=k=0nsu(n,k)xk

这里需要注意,第一类斯特林数根据定义分成了有符号SsS_sSs和无符号SuS_uSu两种。事实上,我们可以很轻松的从这个原始定义推出它的组合意义

因为∑k=0nSu(n,k)⋅xk=xn↑=x(n−1)↑⋅(x+n−1)\sum_{k=0}^nS_u(n,k)·x^k=x^{n\uparrow}=x^{(n-1)\uparrow}·(x+n-1)k=0nSu(n,k)xk=xn=x(n1)(x+n1)=∑k=0n−1Su(n−1,k)xk+1+(n−1)∑k=0n−1Su(n−1,k)xk=\sum_{k=0}^{n-1}S_u(n-1,k)x^{k+1}+(n-1)\sum_{k=0}^{n-1}S_u(n-1,k)x^k=k=0n1Su(n1,k)xk+1+(n1)k=0n1Su(n1,k)xk

对比两边xmx^mxm的系数,可以得到Su(n,m)=Su(n−1,m−1)+(n−1)Su(n−1,m)S_u(n,m)=S_u(n-1,m-1)+(n-1)S_u(n-1,m)Su(n,m)=Su(n1,m1)+(n1)Su(n1,m)继续推有符号的,可以得到Ss(n,m)=Ss(n−1,m−1)−(n−1)Ss(n−1,m)S_s(n,m)=S_s(n-1,m-1)-(n-1)S_s(n-1,m)Ss(n,m)=Ss(n1,m1)(n1)Ss(n1,m)事实上,我们可以完全不用记第一类斯特林数的组合意义,通过公式直接推出来即可。当然记了更好,还可以验证。

所以,根据第一类斯特林数的的定义,得到:∏x=0k−1(n−x)=∑k=0nSs(n,k)xk\prod_{x=0}^{k-1}(n-x)=\sum_{k=0}^nS_s(n,k)x^kx=0k1(nx)=k=0nSs(n,k)xk

于是我们可以得到一个显然的式子是:nm=nm↓−∑k=0m−1Ss(m,k)⋅nkn^m=n^{m\downarrow}-\sum_{k=0}^{m-1}S_s(m,k)·n^knm=nmk=0m1Ss(m,k)nk

我们继续推,发现下降幂的和是可以写成一个组合数的形式的,比方说∑i=mnim↓=∑i=mni!m!(i−m)!m!=m!∑i=mn(im)=m!(n+1m+1)\sum_{i=m}^ni^{m\downarrow}=\sum_{i=m}^n\frac{i!m!}{(i-m)!m!}=m!\sum_{i=m}^n\binom{i}{m}=m!\binom{n+1}{m+1}i=mnim=i=mn(im)!m!i!m!=m!i=mn(mi)=m!(m+1n+1)

而后面那一坨式子也是可以化简的,比方说∑i=0n∑k=0m−1Ss(m,k)⋅ik=∑k=0m−1Ss(m,k)∑i=0nik\sum_{i=0}^n\sum_{k=0}^{m-1}S_s(m,k)·i^k=\sum_{k=0}^{m-1}S_s(m,k)\sum_{i=0}^ni^ki=0nk=0m1Ss(m,k)ik=k=0m1Ss(m,k)i=0nik

发现后面那条式子∑i=0nik\sum_{i=0}^ni^ki=0nikkkk是降了阶的,所以可以边处理边记录一下,就不用重新算了,时间复杂度就变成了O(k2)O(k^2)O(k2)。而处理Ss(m,k)S_s(m,k)Ss(m,k)也是O(k2)O(k^2)O(k2)级别。

事实上如果当你升入初三,Ss(m,k)S_s(m,k)Ss(m,k)就可以运用分治NTTNTTNTT做到O(klog2k)O(klog^2k)O(klog2k)了,虽然然并卵。

但请注意,这种方法虽然时间复杂度是O(k2)O(k^2)O(k2)级别的,但是它并非没有什么用,因为它——不用做除法

6. 第二类斯特林数

第二类斯特林数的组合意义就是nnn个元素分成mmm个集合,且集合非空的方案数。

基本性质是{nm}={n−1m−1}+m⋅{n−1m}\begin{Bmatrix}n\\m\end{Bmatrix}=\begin{Bmatrix}n-1\\m-1\end{Bmatrix}+m\cdot \begin{Bmatrix}n-1\\m\end{Bmatrix}{nm}={n1m1}+m{n1m}

考虑它的通项公式,可以先把所有集合标号,最后除以集合的阶乘即可,那么考虑容斥,枚举非空集合个数iii,可以得到{nm}=1m!∑i=0m(−1)i(mi)(m−i)n\begin{Bmatrix}n\\m\end{Bmatrix}=\frac 1 {m!}\sum_{i=0}^m(-1)^i\binom mi(m-i)^n{nm}=m!1i=0m(1)i(im)(mi)n

接下来继续推导自然数幂和。

显然!!ik=∑j=0k{kj}ij↓i^k=\sum_{j=0}^k\left\{\begin{array}{c}{k}\\{j}\end{array}\right\}i^{j\downarrow}ik=j=0k{kj}ij

继续推导∑i=1nik=∑i=1n∑j=0k{kj}ij↓\sum_{i=1}^ni^k=\sum_{i=1}^n\sum_{j=0}^k\left\{\begin{array}{c}{k}\\{j}\end{array}\right\}i^{j\downarrow}i=1nik=i=1nj=0k{kj}ij=∑i=1n∑j=0k{kj}j!(ij)=\sum_{i=1}^n\sum_{j=0}^k\left\{\begin{array}{c}{k}\\{j}\end{array}\right\} j!\left(\begin{array}{c}{i}\\{j}\end{array}\right)=i=1nj=0k{kj}j!(ij)=∑j=0k{kj}j!∑i=jn(ij)=\sum_{j=0}^k\left\{\begin{array}{c}{k}\\{j}\end{array}\right\} j!\sum_{i=j}^n\left(\begin{array}{c}{i}\\{j}\end{array}\right)=j=0k{kj}j!i=jn(ij)=∑j=0k{kj}j!(n+1j+1)=\sum_{j=0}^k\left\{\begin{array}{c}{k}\\{j}\end{array}\right\} j!\binom{n+1}{j+1}=j=0k{kj}j!(j+1n+1)

很明显,除去预处理第二类斯特林数的复杂度,后面是一样不用做除法的,可以做到O(k)O(k)O(k).

那么时间复杂度决定于预处理第二类斯特林数的复杂度。显然可以用O(k2)O(k^2)O(k2)递推。

然而事实上,我们来看看斯特林数的通项公式:{nm}=1m!∑i=0m(−1)i(mi)(m−i)n\begin{Bmatrix}n\\m\end{Bmatrix}=\frac 1 {m!}\sum_{i=0}^m(-1)^i\binom mi(m-i)^n{nm}=m!1i=0m(1)i(im)(mi)n

一拼凑,咦~{nm}=∑i=0m(−1)ii!⋅(m−i)n(m−i)!\begin{Bmatrix}n\\m\end{Bmatrix}=\sum_{i=0}^m\frac{(-1)^i}{i!}\cdot\frac{(m-i)^n}{(m-i)!}{nm}=i=0mi!(1)i(mi)!(mi)n

这原来可以写成形如∑i=0mf(i)∗g(m−i)\sum_{i=0}^mf(i)*g(m-i)i=0mf(i)g(mi)的卷积形式。于是第一个多项式的第iii项系数是(−1)ii!\frac {(-1)^i}{i!}i!(1)i,另一个多项式的第iii项系数是ini!\frac {i^n}{i!}i!in,卷积后第iii项的系数就是{ni}\begin{Bmatrix}n\\i\end{Bmatrix}{ni}.

于是愉快的将时间变成了O(KlogK)O(KlogK)O(KlogK)

7. 差分表

初三来学习一下差分表吧。

对于任何一个序列a0,a1,...,an,...a_0, a_1, ... , a_n, ...a0,a1,...,an,...我们都可以定义它的差分序列Δa0,Δa1,...,Δan,...\Delta a_0, \Delta a_1, ... ,\Delta a_n, ...Δa0,Δa1,...,Δan,...,其中Δai=ai+1−ai\Delta a_i=a_{ i+1 }-a_iΔai=ai+1ai

类似的,我们可以构造序列{Δan}\{\Delta a_n\}{Δan}的二阶、三阶…kkk阶差分序列。 不妨记为{Δ2an},...,{Δkan}\{\Delta^2 a_n\},...,\{\Delta^k a_n\}{Δ2an},...,{Δkan}

令序列是一个ppp次多项式,那么差分表一个很重要且很显然的性质是:∀n>=0,Δp+1an=0\forall n>=0, \Delta^{p+1}a_n = 0n>=0,Δp+1an=0这是由于每次差分都必然会把最高次项消去!

另外一个很重要的性质就是差分表的线性性,即如果fn=k1gn+k2hnf_n=k_1g_n+k_2h_nfn=k1gn+k2hn,那么一定有∀p,n,Δpfn=k1Δpgn+k2Δphn\forall p, n, \Delta^p f_n=k_1\Delta^p g_n + k_2\Delta^p h_np,n,Δpfn=k1Δpgn+k2Δphn

而其最重要的一个性质就是,任何一个ppp阶多项式,都必定可以由其差分表的第一条对角线确定。为了证明这个结论,不妨先考虑最简单的情况:

差分表的一条对角线为0,...,0,1,0,...0, ..., 0, 1, 0, ...0,...,0,1,0,...,即第一条对角线上只有第ppp个位置为111,其他都为000,那么可以写出这个序列的通项公式fn=c(n)(n−1)(n−2)...(n−p+1)f_n=c(n)(n-1)(n-2)...(n-p+1)fn=c(n)(n1)(n2)...(np+1)

代入n=p,fp=1n=p,f_p=1n=p,fp=1,得到c=1p!c=\frac{1}{p!}c=p!1所以可以得到fn=n!p!(n−p)!=(np)f_n=\frac{n!}{p!(n-p)!}=\tbinom{n}{p}fn=p!(np)!n!=(pn)

那么根据差分表的线性性,我们就可以得知fn=∑i=0pci(ni)f_n=\sum_{i=0}^p c_i\tbinom{n}{i}fn=i=0pci(in)
由于∑k=0nf(k)=∑k=0pck(n+1k)\sum_{k = 0}^n f(k) = \sum_{k = 0}^p c_k {n + 1 \choose k}k=0nf(k)=k=0pck(kn+1)所以利用差分表,我们可以在O(p2)O(p^2)O(p2)的时间复杂度求解类似于∑i=0nfi\sum_{i=0}^n f_ii=0nfi的式子。

回到自然数幂和的问题上,我们把fi=ikf_i=i^kfi=ik代入计算前ppp项的值,通过p2p^2p2的时间复杂度处理出差分表的第一条对角线,设这个对角线为c(p,0),c(p,1),c(p,2),…,c(p,p)c(p, 0), c(p, 1), c(p, 2), \dots, c(p, p)c(p,0),c(p,1),c(p,2),,c(p,p),那么答案就是∑k=0pc(p,k)(n+1k)\sum_{k = 0}^p c(p, k){n + 1 \choose k}k=0pc(p,k)(kn+1)

8. 伯努利数

初三再来学一学伯努利数吧。

根据伯努利数的生成函数定义,可知xex−1=∑i≥0Bi∗xii!\frac{x}{e^{x}-1} = \sum_{i\geq 0} B_{i}*\frac{x^{i}}{i!}ex1x=i0Bii!xi

由于xex−1⋅(ex−1)=x\frac{x}{e^x-1}·(e^x-1)=xex1x(ex1)=x

[xn]xex−1⋅(ex−1)=∑i=0n−1Bii!⋅1(n−i)!=[n=1][x^n]\frac{x}{e^x-1}·(e^x-1)=\sum_{i=0}^{n-1}\frac{B_i}{i!}·\frac{1}{(n-i)!}=[n=1][xn]ex1x(ex1)=i=0n1i!Bi(ni)!1=[n=1]

两边都乘上n!n!n!可以得到∑i=0n−1(ni)Bi=[n=1]\sum_{i=0}^{n-1}\binom{n}{i}B_i=[n=1]i=0n1(in)Bi=[n=1]

这是伯努利数的一个基本性质。后面会用到。

我们再定义一个多项式Bn(t)B_n(t)Bn(t)表示Bn(t)=∑k=0n−1Bk∗tn−k∗CnkB_{n}(t) = \sum_{k=0}^{n-1} B_{k} * t^{n-k}*C_{n}^{k}Bn(t)=k=0n1BktnkCnk

然后我们发现
Bn(t+1)−Bn(t)=∑k=0n−1Bk∗⟮(t+1)n−k−tn−k⟯CnkB_n(t+1)-B_n(t)=\sum_{k=0}^{n-1} B_{k}*\lgroup(t+1)^{n-k} - t^{n-k}\rgroup C_{n}^{k}Bn(t+1)Bn(t)=k=0n1Bk(t+1)nktnkCnk=∑k=0n−1Bk∗(∑i=0n−k−1Cn−ki∗ti)∗Cnk=\sum_{k=0}^{n-1} B_{k}*(\sum_{i=0}^{n-k-1} C_{n-k}^{i} * t^{i})* C_{n}^{k}=k=0n1Bk(i=0nk1Cnkiti)Cnk=∑k=0n−1Bk∗(∑i=0n−k−1Cn−ki∗ti∗Cnk)=\sum_{k=0}^{n-1} B_{k}*(\sum_{i=0}^{n-k-1} C_{n-k}^{i} * t^{i}*C_{n}^{k})=k=0n1Bk(i=0nk1CnkitiCnk)=∑i=0n−1Bk∗∑i=0n−k−1n!tii!k!(n−k−i)!=\sum_{i=0}^{n-1}B_k*\sum_{i=0}^{n-k-1}\frac{n!t^i}{i!k!(n-k-i)!}=i=0n1Bki=0nk1i!k!(nki)!n!ti=∑k=0n−1Bk∗(∑i=0n−k−1Cn−ik∗ti∗Cni)=\sum_{k=0}^{n-1} B_{k}*(\sum_{i=0}^{n-k-1} C_{n-i}^{k} * t^{i}*C_{n}^{i})=k=0n1Bk(i=0nk1CniktiCni)=∑i=0n−1Cni∗ti∗∑k=0n−1−iBk∗Cn−ik=\sum_{i=0}^{n-1} C_{n}^{i}*t^{i}*\sum_{k=0}^{n-1-i} B_{k}*C_{n-i}^{k}=i=0n1Cnitik=0n1iBkCnik

注意到后面只有当n−i−1=0n-i-1=0ni1=0时值为111,于是Bn(t+1)−Bn(t)=n∗tn−1B_n(t+1)-B_n(t)=n*t^{n-1}Bn(t+1)Bn(t)=ntn1

然后我们考虑差分,就有∑t=0n−1Bk(t+1)−Bk(t)=k⋅∑i=0n−1ik−1\sum_{t=0}^{n-1}B_k(t+1)-B_k(t)=k·\sum_{i=0}^{n-1}i^{k-1}t=0n1Bk(t+1)Bk(t)=ki=0n1ik1Bk+1(n+1)=(k+1)⋅∑i=0nikB_{k+1}(n+1)=(k+1)·\sum_{i=0}^ni^kBk+1(n+1)=(k+1)i=0nik

可得自然数幂和∑i=0nik=1k+1⋅∑i=0kBink+1−i(k+1i)\sum_{i=0}^ni^k=\frac{1}{k+1}·\sum_{i=0}^kB_in^{k+1-i}\binom{k+1}{i}i=0nik=k+11i=0kBink+1i(ik+1)

问题转化成了求BiB_iBi,注意到它的生成函数定义,事实上我们只需要求∑i≥0xi(i+1)!\sum_{i\ge 0}\frac{x^i}{(i+1)!}i0(i+1)!xi在模xk+1x^{k+1}xk+1的逆元即可。

时间复杂度O(KLogK)O(KLogK)O(KLogK),当然如果递推的话,也是可以轻松做到O(k2)O(k^2)O(k2)的。

9. 拉格朗日插值法

两大作用:

  1. 快速根据点值逼近原函数.

  2. 取点值对大于nnn唯一确定nnn次多项式.

Example

例如对于∑i=1ni=n(n+1)2\sum\limits_{i=1}^ni=\frac{n(n+1)}{2}i=1ni=2n(n+1)

我们知道它的通项公式是二次的,所以我们只需要三个点值对就可以唯一确定这个多项式:(1,1),(2,3),(3,6)(1,1),(2,3),(3,6)(1,1),(2,3),(3,6)

General method

对于已知的n+1n+1n+1个点对(x0,y0),(x1,y1)...(xn,yn)(x_0,y_0),(x_1,y_1)...(x_n,y_n)(x0,y0),(x1,y1)...(xn,yn),求n+1n+1n+1个函数fif_ifi,使得该函数在xix_ixi处取得对应的yiy_iyi值,其余xjx_jxj处为000,最后把这n+1n+1n+1个函数线性结合即可。

fi(x)=∏j≠i(x−xj)∏j≠i(xi−xj)∗yif_i(x)=\frac{\prod\limits_{j\neq i}(x-x_j)}{\prod\limits_{j\neq i}(x_i-x_j)}*y_ifi(x)=j̸=i(xixj)j̸=i(xxj)yig(x)=∑i=0nfi(x)g(x)=\sum_{i=0}^nf_i(x)g(x)=i=0nfi(x)

Practice

例如我们要求自然数幂和.

各种方法可以证明iki^kik的和是k+1k+1k+1次的, 所以我们只需要给出k+2k+2k+2个点值表达,就可以求得通项公式.

S(n)=∑i=1nikS(n)=\sum_{i=1}^n i^kS(n)=i=1nik, 则
S(n)=∑i=1k+2yi∏j=1,i≠jk+2n−xjxi−xj=∑i=1k+2yi∏j=1,i≠jk+2(n−j)∏j=1,i≠jk+2(i−j)S(n)=\sum_{i=1}^{k+2}y_i\prod_{j=1,i\neq j}^{k+2}\frac {n-x_j}{x_i-x_j}=\sum_{i=1}^{k+2}y_i\frac {\prod_{j=1,i\neq j}^{k+2}(n-j)}{\prod_{j=1,i\neq j}^{k+2}(i-j)}S(n)=i=1k+2yij=1,i̸=jk+2xixjnxj=i=1k+2yij=1,i̸=jk+2(ij)j=1,i̸=jk+2(nj)

那么时间复杂度就在预处理yiy_iyi上面了, 利用线筛,可以做到O(k)O(k)O(k)级别.

后面的那一部分可以预处理,具体的说,就有:S(n)=∑i=1k+2yipre[i−1]suf[i+1][(−1)k+2−i(i−1)!(k+2−i)!]−1S(n)=\sum_{i=1}^{k+2}y_ipre[i-1]suf[i+1][(-1)^{k+2-i}(i-1)!(k+2-i)!]^{-1}S(n)=i=1k+2yipre[i1]suf[i+1][(1)k+2i(i1)!(k+2i)!]1

CodeCodeCode

时间复杂度:O(klnklog2k)=O(k)O(\frac{k}{ln_k}log_2k)=O(k)O(lnkklog2k)=O(k).

另外,注意逆元要预处理,实测:k=1e7k=1e7k=1e70.9s0.9s0.9s,可以说是非常优秀了

#include <bits/stdc++.h> 

#define F(i,a,b) for (int i = a; i <= b; i ++)
#define G(i,a,b) for (int i = a; i >= b; i --)

const int Mo = 998244353, M = 1e6 + 10;

using namespace std;

int l, r, k, m, y[M], z[M], jc[M], suf[M], pre[M];
bool bz[M];

int ksm(int x, int y) {
	int ans = 1;
	for (; y; y >>= 1, x = (1ll * x * x) % Mo)
		if (y & 1)
			ans = (1ll * ans * x) % Mo;
	return ans;
}

void Init() {
	scanf("%d%d%d", &l,&r,&k), y[1] = 1, m = k + 2;
	F(i, 2, m) {
		if (!bz[i])
			z[++ z[0]] = i, y[i] = ksm(i, k);
		F(j, 1, z[0]) {
			if (z[j] * i > m) break;
			bz[z[j] * i] = 1;
			y[z[j] * i] = (1ll * y[z[j]] * y[i]) % Mo;
			if (i % z[j] == 0) break;
		}
	}
	F(i, 2, m)
		y[i] = (y[i - 1] + y[i]) % Mo;
	jc[0] = 1;
	F(i, 1, m)
		jc[i] = 1ll * jc[i - 1] * i % Mo;
	jc[m] = ksm(jc[m], Mo - 2);
	G(i, m - 1, 1)
		jc[i] = 1ll * jc[i + 1] * (i + 1) % Mo;
}

int Solve(int n) {
	pre[0] = suf[m + 1] = 1;
	F(i, 1, m)
		pre[i] = 1ll * pre[i - 1] * (n - i) % Mo;
	G(i, m, 1)
		suf[i] = 1ll * suf[i + 1] * (n - i) % Mo;

	int Ans = 0;
	F(i, 1, m)
		Ans = (Ans + 1ll * y[i] * pre[i - 1] % Mo * suf[i + 1] % Mo * (((k-i+2)&1) ? (-1) : 1) * jc[i - 1] % Mo * jc[k + 2 - i] % Mo) % Mo;
	return Ans;
}

int main() {
	Init();

	printf("%d\n", (Solve(r) - Solve(l - 1) + Mo) % Mo);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值