由解题思路1.0我们能得到最后的结果为
而根据题目要求,我们要对结果模10从而得到结果。
易知,大数运算的时间复杂度超过O(1),若这样写(粘贴的灵神的代码
class Solution:
def triangularSum(self, nums: List[int]) -> int:
n = len(nums)
# 直接调用 math.comb 算出来的组合数很大,更快的写法见【Python3 预处理】
return sum(comb(n - 1, i) * x for i, x in enumerate(nums)) % 10
作者:灵茶山艾府
链接:https://leetcode.cn/problems/find-triangular-sum-of-an-array/solutions/1390137/o-by-endlesscheng-952i/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
先不论大数运算给时间复杂度的增幅,就从直接调用Math.comb函数,时间复杂度为
所以我们考虑预处理组合数的模数,使复杂度降低。
这题巧妙之处在于模数是10而不是传统经常碰到的质数。
假如我们碰到了质数,那么我们可以根据费马小定理(MOD必须是质数
用以下方式进行预处理。
MX = 100000
MOD = 10**9 + 7
f = [0]*(MX + 1)
inv_f = [0]*(MX + 1)
for i in range(0,MX + 1):
if i == 0 :
f[i] = 1
else:
f[i] = ((f[i-1]%MOD)*i)%MOD
mx_inv = pow(f[MX],MOD - 2,MOD )
# print(mx_inv)
inv_f[-1] = mx_inv
for i in range(MX-1,-1,-1):
inv_f[i] = (inv_f[i+1]*(i+1))%MOD
# print((inv_f[i]*f[i])%MOD)
def comb(a,b):
return (f[a]*inv_f[b]*inv_f[a-b])%MOD
print(comb(6,2))
而显然不是质数,对于合数,便进入了我们这题最精彩的部分,合数的模运算。
先讨论欧拉定理加质因数分解的方法。
什么是欧拉定理,也就是在a和b互质的前提下
顺带提一提欧拉函数,我记得一道蓝桥杯的题目用到过:
欧拉函数是指小于num的数中与num互质的数的数量
当b是质数的时候,
(直观理解是质数与任何非他自身的数互质,注意1也与num互质)
当b是合数的时候,
是b的所有质因子。
故欧拉函数的计算公式有代码如下:
import math
def Phi(P):
K = P # 用来保存 P 的值,后面会用于计算
for i in range(2, int(math.sqrt(P)) + 1):
if P % i == 0: # 如果 i 是 P 的因数
K = K // i * (i - 1) # 将 K 按照公式缩小
while P % i == 0: # 如果 i 是 P 的因数,除掉所有 i
P //= i # P 除以 i,直到 P 不能被 i 整除为止
if P > 1: # 如果 P 本身大于 1,说明 P 是一个大于 1 的质因数
K = K // P * (P - 1) # 继续按照公式处理
return K
而本题为了满足欧拉定理a与b互质的条件,对b进行质因数拆分,即10被拆分为了2和5。
故有
令
则有
今天就写这里了,刷道题就睡了。慢慢来吧