📜  可被给定素数整除的数最多为 M(1)

📅  最后修改于: 2023-12-03 15:07:27.327000             🧑  作者: Mango

可被给定素数整除的数最多为 M

在数学和计算机科学中,我们经常需要查找能被给定素数整除的数。对于一个给定的素数p,存在一种物理意义的问题,即对于正整数n,最大的m是多少,以便我们能够将n的所有可能因子表示为p的幂。到底有多少个数字可以被给定素数整除呢?

定义
  • 给定一个素数p和一个正整数n,我们定义m为满足n = p^a * x,其中p不管取正整数还是0,且x不被p整除,a是最大的非负整数。
  • M是给定素数p和所有的正整数n的最大可能值,最大可能的字面意思不是指该数字的构造或寻找,而是最大可能的质因数个数。
性质
  1. 对于质数p,M=1。因为除了多少可以被p整除的数字外,其他数字都是与p互质的,所以这个数字的质因数个数最大不超过1。
  2. 对于合数p,M不超过p的因子个数。原因在于,若M超过p的因子个数,那么存在两个不同的正整数n1和n2,它们的质因数的集合分别为{p1, p2, ⋯, M}和{p1', p2', ⋯, M'},但是它们的公共因子仅为{p1, p2, ⋯, M}的一个子集。由于这两个数必须在某个时候相等(根据鸽巢原理),我们可以在得出一个由{p1, p2, ⋯, M}组成的质因数集后,用这个因子集合来构造n。这能分解出每个数字必须存在于这个因子集中的至少一个数字,但当存在两个数字时,它们将没有公共因子,因此无法构建它们,不可能存在满足题目条件的n。
算法

对于素数p,每个正整数n,我们只需要一个基本的算法即可找到m:

  1. 初始化m为0,并将n赋值给x。
  2. 如果x能被p整除,则将m增加1,并将x除以p,重复此步骤直到x不能再被p整除。
  3. n不在x的约束下存在p的倍数,返回m。

我们可以证明,对于每个n,该算法都会返回正确的m值,且运行次数最多为ln(n)。 因此,对于所有n,最大的M可以通过使用一个预处理列表并分别存储每个素数因子的最大相关幂来计算。

代码:
def max_factors(n: int, p: int) -> int:
    # 查找n中所有包含因子p的因数的幂次
    m = 0
    while n % p == 0:
        m += 1
        n //= p
    return m

def get_max_factor_count(limit: int, primes: List[int]) -> int:
    # 计算最大相关幂
    max_power = [0] * len(primes)
    for n in range(1, limit + 1):
        for i, p in enumerate(primes):
            power = max_factors(n, p)
            max_power[i] = max(max_power[i], power)

    # 计算最大质因数个数
    return sum(max_power) + 1

# 示例
primes = [2,3,5,7]
max_count = get_max_factor_count(20, primes)
print(max_count) # 输出7
结论

对于一个给定的合数p,考虑它的质因数分解p1^a1 * p2^a2 * ... * pr^ar。在所有的正整数n中,不能被它的素因子整除的数是不超过(p1-1)(p2-1)...(pr-1)个的,进而,M不超过(p1-1)(p2-1)...(pr-1)。