[CP] 因子个数的分布规律

这段时间没有怎么练习,昨晚打 Div.4 的时候居然卡在 E 了 = =。不过,我觉得这两件事情并没有联系,纯粹是我太菜的缘故。

看 E 的官方题解时发现了一个比较 counter-intuitive 的东西:

image

注意最后一行:“所有小于等于 105 的数最多有 128 个因子”。作者毫无根据地写下了这段话,隐含着某种 “显然”“易得” 的意味。有两种可能——要么是他忘记写推导过程了,要么就是其背后的规律非常简单,按按计算器就能得到结果。

出于对作者的信任,我先考虑第二种可能。我想,自己是不是错过了叫 “因子个数的分布规律” 这样的重要公式?

到网上查了查,并没有发现这样的公式。

于是我决定写个程序计算一下,看看到底有没有规律:

import matplotlib.pyplot as plt
import numpy as np
from copy import copy
n = int(1e7)
notPrime = [False] * (n + 1)
minp = [0] * (n + 1)
primes = []
for i in range(2, n + 1):
if not notPrime[i]:
primes.append(i)
minp[i] = i
for p in primes:
num = i * p
if num > n:
break
notPrime[num] = True
minp[num] = p
if i % p == 0:
break
print("Sieving completed.")
facNum = [1] * (n + 1)
for i in range(2, n + 1):
j = copy(i)
d = {}
while j != 1:
if minp[j] in d:
d[minp[j]] += 1
else:
d[minp[j]] = 1
j //= minp[j]
for cnt in d.values():
facNum[i] *= cnt + 1
print("Factorization completed.")
plt.plot(np.linspace(1, n, n), facNum[1:])
plt.grid()
plt.show()

原理是利用欧拉筛法计算出给定范围内的所有素数,然后对范围内的每个数进行素因子分解,再根据算术基本定理计算出其因子个数。不知道有没有更简单的办法,不过程序跑得还挺快的——1e7 的规模花了 18s。

以下是结果(纵轴为因子个数):
image

image
image
image

坏消息是,虽然不能断定因子个数的分布没有规律,但从结果来看应该是没有规律的(其实不用算也知道,由于素数的因子个数固定是 2,就算不考虑那些因子数量比较少的合数,最终的曲线也应该是起起伏伏的)。

好消息是,它的增长速度很慢,范围扩大 100 倍,范围内最多的因子个数大概是原来的四倍,因此估计 [1,1e8] 内最多的因子个数为 1600 左右。顺带一提我后来单独算了下 1e8 这个数的因子个数,结果是 81,某种程度上也印证了前面所说的 “没有规律” 这一结论。

2024-04-13 更新

上面的图太乱了,感觉绘制上界会更直观。

记横轴上某个点为 x,则对应曲线的纵坐标表示的是到 x 之前(包括 x)最多的因子个数。

image

image

2024-11-26 更新

我突然发现自己的方法十分愚蠢。事实上,只需要以 n 为分界点进行因子分解即可!

posted @   ZXPrism  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示