📅  最后修改于: 2023-12-03 14:44:19.694000             🧑  作者: Mango
Mobius函数属于数论分析中的一类算术函数,用于描述自然数分解质因数后的奇偶性。若一个自然数$n$的质因数分解中有重复的质因数,则定为$0$;若无,则为$1$或$-1$。在本套装中,我们实现了关于Mobius函数的四个算法:积性函数、DP函数、杜教筛、整除分块。
本套装包含以下功能:
mobius_multiplicative
函数实现了积性函数版本的Mobius函数。
from typing import List
def mobius_multiplicative(n: int) -> int:
"""
Calculate Mobius function using multiplicative function.
"""
mobius = 1
p = 2
while n > 1:
if n % p == 0:
n //= p
if n % p == 0:
return 0
mobius = -mobius
p += 1
return mobius
该函数将$n$质因数分解,若有一个质数$p$的幂次$>1$,则返回$0$;否则返回$1$或$-1$。
mobius_dp
函数使用动态规划实现了计算前缀范围内的Mobius函数值。
def mobius_dp(n: int) -> List[int]:
"""
Calculate Mobius function using DP.
"""
mobius = [1] * (n + 1)
for i in range(2, n + 1):
if mobius[i] != 1:
continue
for j in range(i, n + 1, i):
mobius[j] *= -1
if j // i % i == 0:
mobius[j] = 0
return mobius
该函数使用了Mobius函数的前缀积性质,使用DP从小到大计算每个数的Mobius函数值。
mobius_du_jiaosai
函数使用杜教筛实现了计算前缀范围内的Mobius函数值。
def mobius_du_jiaosai(n: int, prime: List[int]) -> List[int]:
"""
Calculate Mobius function using Du Jiaosai method.
"""
mobius = [1] * (n + 1)
for p in prime:
for j in range(p, n + 1, p):
mobius[j] *= -1
for j in range(p*p, n + 1, p*p):
mobius[j] = 0
return mobius
该函数使用了杜教筛,使用前$n$个质数筛出前缀范围内的Mobius函数值。
mobius_divide_conquer
函数使用整除分块实现了计算前缀范围内的Mobius函数值。
def mobius_divide_conquer(n: int, b: int = 500) -> List[int]:
"""
Calculate Mobius function using divide-and-conquer.
"""
mobius = [1] * (n + 1)
for i in range(2, n + 1):
if mobius[i] != 1:
continue
for j in range(i*i, min(n + 1, i*b), i*i):
mobius[j] = 0
for j in range(max(i*b, (n // i + 1)), n + 1):
mobius[j] = mobius_multiplicative(j // i) * (-1)
return mobius
该函数使用了整除分块,将$n$划分为大小为$b$的块,对于每个块$i$,使用筛法计算出$i$到$i+b$的Mobius函数值,再使用积性函数计算出$i+b$到$n$的Mobius函数值。
mobius_multiplicative(n: int) -> int
输入一个正整数$n$,返回$n$的Mobius函数值。若$n$有一个质因数的幂次$>1$,则返回$0$;否则返回$1$或$-1$。
mobius_dp(n: int) -> List[int]
输入一个正整数$n$,返回长度为$n+1$的列表,列表中第$i$个元素表示$1$到$i$的Mobius函数值。
mobius_du_jiaosai(n: int, prime: List[int]) -> List[int]
输入一个正整数$n$和一个不大于$n$的质数列表$prime$,返回长度为$n+1$的列表,列表中第$i$个元素表示$1$到$i$的Mobius函数值。
mobius_divide_conquer(n: int, b: int = 500) -> List[int]
输入一个正整数$n$和一个正整数$b$(可选,默认值为$500$),返回长度为$n+1$的列表,列表中第$i$个元素表示$1$到$i$的Mobius函数值。