0330 欧拉数
* * * *
拉格朗日计划
* * * *
欧拉数

数列an的定义如下 an={1n<0,i=1anii!n0. 它的前几项是 a0=11!+12!+13!+=e1a1=e11!+12!+13!+=2e3a2=2e31!+e12!+13!+=72e6, 可以发现an总是可以表达为 an=Ane+Bnn!, 的形式,其中An,Bn均为整数。例如 a10=328161643e65269448610!,A109+A109模77777777的余数。

本题难度:



解答

Cn=An+Bn,可以观察发现2An+Bn=n!,由于这一关系的存在,Cn事实上可以写成不同的形式,以下使用的是 Cn=k=0n1(nk)Ckk=1nn!k!, 由于77777777=7×11×73×101×137,因此可以计算Cn模每个素因子的结果,再用中国剩余定理将其组合。

右侧两个求和项可以分别用杨辉三角和秦九韶法(以下代码中的变量q)递推计算。

可以观察到(证明较繁琐),Cn模素因子p的结果是周期为p(p1)的序列,因此只需计算大约一万项即可得结果15955822

注:中国剩余定理的简单版本韩信点兵是我国小学奥数的传统内容,此处由于涉及的素数很小,直接遍历Zp来找出乘法逆。

注2:因需使用math.prod函数,以下代码为Python 3。

import math

def inverse(a,p):
  x=1
  while (x*a)%p!=1:
    x+=1
  return x 

d={}
for p in [7,11,73,101,137]:
    c=[0]
    q=0
    pascal=[1]
    for i in range(1,10**9%(p*(p-1))+1):
        q=(i*q+1)%p
        pascal=[1]+[(pascal[j]+pascal[j+1])%p for j in range(i-1)]+[1]
        c.append((sum((pascal[j]*c[j])%p for j in range(i))+q)%p)
    d[p]=c[-1]

n=math.prod(d.keys())
print((-(sum(d[p]*inverse(n//p,p)*n//p for p in d)%n))%77777777)