【数学】【P5150】 生日礼物

Description

给定 n,求

i j [lcm(i,j) = n]

input

一行一个整数代表 n

Output

一行一个整数代表答案

Hint

1  n  1016

Solution

一开始看到这个形式以为是反演,然后看到数据范围就自闭了……

然后发现这是个唯一分解定理题……

吐槽一下标算 O(n) 暴力卡常 范围出1e16也太[数据删除]了吧(大雾

然后用py写了一发和标算差不多的暴力,惨遭卡常

所以这里来提供一种 O(n3) 的方法!

其实就是讨论里 @mrsrz 神仙的第一种踩标算做法

n = i=1kpici

x = i=1kpidi

y = i=1k piei

其中 p 为质数。

则显然有

lcm(x,y) = n   i  [1,k],ci = max(di,ei)

我们考虑固定 xi 位指数即 di = ci,则 ei[0,ci] 都是合法的,共 ci + 1 中选法。将 x,y 反过来同样成立。但是注意固定 di = ci 时令 ei = ci 的选法和反过来是一样的,于是要把这个方案扣除 1

所以对于第 i 个质因子的方案数为 (2 ×ci + 1)。根据乘法原理,总方案数为

i=1k (2 × ci + 1)

于是 O(n) 分解一下,发现py被卡常了。我们考虑一种更优秀的做法:

我们在分解质因数时,分解到 n3,即当 i3 > n 时停止。考虑现在 n 除掉已经筛出的质因子后剩下的值共有如下几种情况:

剩下 1:这种情况对答案无贡献,无需理会

剩下的数是一个质数:显然这个剩下的数是 n 的最后一个质因子,并且指数显然为 1,于是直接将答案乘 3 即可

考虑除去这两种情况外,剩下的数只能是两个质数的积,而不可能是更多质数的积。

证明上,可以设剩下的最小的质数是 p,则有 p > n3,假设是 k 个质数的乘积,那么显然有剩下的数字 dn  pk。由于 p3 > (n3)3 = ndn  n,则在 k  3 时产生矛盾,于是 k  2

再分两种情况:

剩下的数是一个质数的平方:直接将答案乘 5 即可

否则一定是两个质数相乘。考虑每个质数贡献 3,所以将答案乘上 9 即可。

考虑如何快速判断剩下的数字是一个质数:直接进行米勒拉宾质数判定,时间复杂度 O(logn)

考虑不损失精度的判断一个数是一个完全平方数:直接进行二分开方,时间复杂度 O(logn)

于是总时间复杂度 O(n3),踩爆标算

Code

def mpow(x, y, p):
	_ret, _temp = 1, x
	while y:
		if y & 1:
			_ret = _ret * _temp % p
		_temp = _temp * _temp % p
		y >>= 1
	return _ret

def ML(x, n):
	if n == x: return 1
	sn = n - 1
	s, d = n - 1, 0
	while not (s & 1):
		s >>= 1
		d += 1
	t = mpow(x, s, n)
	if t == 1 or t == -1: return 1
	for i in range(d):
		if t == sn: return 1
		t = t * t % n
	return 0

def IsPrime(x):
	if not (x & 1):
		if x == 2: return 1
		else: return 0
	elif not ML(2, x): return 0
	elif not ML(7, x): return 0
	elif not ML(61, x): return 0
	else: return 1

def IsPow(x):
	l, r, mid, = 1, x, 0
	while l <= r:
		mid = (l + r) >> 1
		k = mid * mid
		if k < x: l = mid + 1
		elif k == x: return 1
		else: r = mid - 1
	return 0

n = int(input())

ans, i, dn = 1, 2, n

while (i * i * i) <= n:
	if (dn % i) == 0:
		cnt = 0
		while (dn % i) == 0:
			dn //= i
			cnt += 1
		ans *= (cnt << 1) + 1
	i += 1
if dn != 1:
	if IsPrime(dn):
		ans *= 3
	elif IsPow(dn):
		ans *= 5
	else:
		ans *= 9
		
print(ans)
posted @   一扶苏一  阅读(326)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示