Project Euler 266

Project Euler 266

题目

Pseudo Square Root

The divisors of \(12\) are: \(1,2,3,4,6\) and \(12\).

The largest divisor of \(12\) that does not exceed the square root of \(12\) is \(3\).

We shall call the largest divisor of an integer \(n\) that does not exceed the square root of \(n\) the pseudo square root (\(\text{PSR}\)) of \(n\).

It can be seen that \(\text{PSR}(3102)=47\).

Let \(p\) be the product of the primes below \(190\). Find \(\text{PSR}(p) \bmod 10^{16}\).

解决方案

质数的个数只有\(m=42\)个,比较容易想到meet-in-the-middle思想。

\(n\)为这些质数的积。前\(21\)个质数可以产生\(n\)的因子的一部分,存放在数组\(lm\)中,后\(21\)个质数也可以产生\(n\)的因子的另一部分,放在数组\(rm\)中。

那么,\(lm,rm\)中任意一对数的乘积组合就一一对应了\(n\)的因子。

因此在\(lm\)中,每遍历一个数\(x\),就在\(rm\)中找到一个最大的\(y\),使得\(xy\le \sqrt{N}\)

采用排序后用双指针进行遍历的方法就可以完成这个问题。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from tools import int_sqrt, get_prime

N = 190
mod = 10 ** 16
pr = get_prime(N)
lm, rm = [1], [1]
for p in pr[:len(pr) >> 1]:
lm += [x * p for x in lm]
for p in pr[len(pr) >> 1:]:
rm += [x * p for x in rm]
sq = int_sqrt(lm[-1] * rm[-1])
lm.sort()
rm.sort()
r = len(rm) - 1
ans = 0
for l in range(len(lm)):
while r >= 0 and lm[l] * rm[r] > sq:
r -= 1
if r < 0:
break
ans = max(ans, lm[l] * rm[r])
ans %= mod
print(ans)