Project Euler 355

Project Euler 355

题目

Maximal coprime subset

Define $Co(n)$ to be the maximal possible sum of a set of mutually co-prime elements from ${1, 2, \dots, n}$.

For example $Co(10)$ is $30$ and hits that maximum on the subset ${1, 5, 7, 8, 9}$.

You are given that $Co(30) = 193$ and $Co(100) = 1356$.

Find $Co(200000)$.

解决方案

令$N=200000$,令函数$f(n,p)$表示求$p$最大的质数幂$p^k\le n$。

本题基于这个假设完成:被选上集合的数$n$,必定是以下两类数之一:

  • $f(n,p)$.对于$N$以内的任何一个质数$p$。
  • $f\left(\left\lfloor\dfrac{n}{q}\right\rfloor,p\right)\cdot q$,其中$p$是一个质数,$q$是一个大于$\lfloor\sqrt{N}\rfloor$的质数。

如果质数$p,q$构造出了候选答案的第二类数,那么其它第二类数必定不能含有$p,q$这两个质因子,因此我们可以将其转化成最小费用最大流问题来解决。一开始我们先假设候选答案中只有第一类数,其总和为$s$,往后再逐渐添加第二类数。

假设小于等于$\lfloor\sqrt{N}\rfloor$的质数为集合$P$,其余质数为集合$Q$。对于$p\in P,q \in Q$,如果$f\left(\left\lfloor\dfrac{n}{q}\right\rfloor,p\right)\cdot p>f(n,p)+q$,那么从节点$p$到节点$q$连一条容量为$1$,费用为$-\left(f\left(\left\lfloor\dfrac{n}{q}\right\rfloor,p\right)\cdot p-f(n,p)-q\right)$的边。那么,将源点连向$P$中的每个节点,将$Q$中的每个节点连向汇点,这些边的容量都为$1$,费用都为$0$。

最终使用networkx库中的max_flow_min_cost方法完成计算。将答案添加到$s$中,成为最终答案。需要注意的是,我们求的费用是最大值,因此整张图的费用权值都是负数。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from tools import get_prime
import networkx as nx

N = 200000


def cal(n, p):
m = 1
while m * p <= n:
m *= p
return m


pr = get_prime(N)
g = nx.DiGraph()
ans = 1
st, ed = [], []
s, t = -1, -2
for p in pr:
ans += cal(N, p)
if p ** 2 <= N:
g.add_edge(s, p, capacity=1, weight=0)
st.append(p)
elif p + p <= N:
g.add_edge(p, t, capacity=1, weight=0)
ed.append(p)
for p in st:
for q in ed:
if p * q > N:
break
k = cal(N // q, p) * q
if cal(N, p) + q < k:
g.add_edge(p, q, capacity=1, weight=-(k - cal(N, p) - q))

ans += -nx.cost_of_flow(g, nx.max_flow_min_cost(g, s, t))
print(ans)

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
Ujimatsu Chiya 微信 微信
Ujimatsu Chiya 支付宝 支付宝