20 分做法
直接按照定义计算。
先预处理阶乘和逆阶乘。对于每个 x=0,1,…,n,枚举 i=0,1,…,min(k,x),用递推维护下降幂 xi,累加
x!(n−x)!xi
即可。
时间复杂度 O(nk),可以通过 n 较小的数据。
另有 20 分做法(k=0)
当 k=0 时,
f(x)=x!(n−x)!1.
因此
S(n)=x=0∑nx!(n−x)!1=n!1x=0∑n(xn)=n!2n.
直接计算 2n⋅(n!)−1modp 即可。
另有 20 分做法(k=1)
当 k=1 时,
f(x)=x!(n−x)!1+x.
于是
S(n)=x=0∑nx!(n−x)!1+x=0∑nx!(n−x)!x.
第一部分为 n!2n。
第二部分中
x=0∑nx(xn)=n2n−1,
所以
x=0∑nx!(n−x)!x=n!n2n−1=(n−1)!2n−1.
答案为
n!2n+(n−1)!2n−1.
100 分做法
关键是把分母中的阶乘改写为组合数:
x!(n−x)!1=n!1(xn).
于是
S(n)=n!1i=0∑kx=0∑nxi(xn).
当 x<i 时,下降幂 xi 中包含因子 0,对应项为 0。因此只需要考虑 x≥i。
对于内层求和,有
xi(xn)=(x−i)!x!⋅x!(n−x)!n!=(x−i)!(n−x)!n!.
令 y=x−i,则
x=i∑nxi(xn)=x=i∑n(x−i)!(n−x)!n!=niy=0∑n−i(yn−i)=ni⋅2n−i.
代回原式:
S(n)=n!1i=0∑kni⋅2n−i.
又因为
n!ni=(n−i)!n!⋅n!1=(n−i)!1,
所以
S(n)=i=0∑k(n−i)!2n−i.
令 j=n−i,得到
S(n)=j=n−k∑nj!2j.
这正是级数 ∑j!2j 的一段连续子和。
实现时不需要保存所有阶乘。若 p=2,由 n<p 可知只有 n=0 或 n=1,直接计算即可。
下面考虑 p 为奇质数的情况。先线性计算 n!modp,再用费马小定理求出 (n!)−1,得到最后一项
n!2n.
设
Tj=j!2j.
则
Tj−1=Tj⋅2j.
因此可以从 j=n 倒着递推到 j=n−k,边递推边累加答案。
由于题目保证 p 为质数且 n<p,所有 1,2,…,n 在模 p 意义下都有逆元,阶乘也不为 0。
时间复杂度 O(n+k),由于 k≤n,也就是 O(n)。空间复杂度 O(1)。