2018焦作站现场赛E题

水题没人写题解,都直接上Java代码……那我写一个。

计蒜客题面:https://nanti.jisuanke.com/t/A2203
题意:如果i是完全平方数(>=4)的倍数,那么i号电阻的阻值为无穷大,否则为i。
现在有编号为1~n的集合,每个集合包含若干个电阻,编号为i的集合包含所有编号为i的约数的电阻。求一个集合,使该集合内所有电阻的并联阻值最小。
关键的来了:n<=10100


首先,对于一个电阻,如果它能改变总电阻,那么着它的阻值不是无穷大,因此它的每个质因子最多被乘了一次。所以对于每个电阻的集合,它的编号的约数中,只有1、质因数、以及若干个不同质因数的积是有效的。另外,如果一个数的约数包含了若干个质因数,那么这个数的约数也必然包含这些质因数的积。 这样,只要选出积不超过n的若干个质数,再加上公共约数1,就是要找的集合。

那么选取哪些质数呢?从让阻值尽量大的角度来讲,在质因子数量相同的情况下,应当选择尽量小的质数。以比较集合6和集合10为例,6=1×2×3,10=1×2×5,显然电阻5和(2×5=10)两个电阻都比3和(2×3=6)的阻值大,因此质因子5不如质因子3优。另外,由于要选的集合编号不超过n,在质因子数量相同的情况下,如果能选较大的质因子,必然能选编号较小的质因子。因此选质因子的策略为:在质因子的积不超过n的前提下,尽量选取最小的质因子,即依次选取2,3,5,7……

然后就是计算总电阻。题目给了电阻公式,此处R1,R2,R3,R4……Rk依次等于1,2,3,5……(2×3×5×……×p),其中p为最大的质因子。

上下同时乘以Rk,得到:R=Rk/(1+2+3+5+……+p+2×3+2×5+3×5+……+2×3×5+……+Rk)
分母中,对于每一个含有p的项,提取p,得:p×(1+2+3+5+……+2×3+2×5+3×5+……)+(1+2+3+5+……+2×3+2×5+3×5……)=(p+1)×(1+2+3+5+……+2×3+2×5+3×5+……)
观察发现,(p+1)的系数是不取p的情况下的分母值。那么这个分母就形成了递推式,后一项是前一项的p+1倍,第一项为1。这样用递推式求出分母,约分即可。
用欧拉筛预处理出前若干项质数,它们的积至少要超过n的最大值10100,经过验证,求出前300项质数已经足够了。
然后就是py= = Java不会(而且高精度类似乎比较糟),c++……考场手打高精度???
人生苦短,我用python。

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
import math

m,l=300,0
prime,a=[],[]
for i in range(0,m+1):
a.append(1)
a[1]=0

for i in range(2,m+1):
if a[i]:
prime.append(i)
for j in prime:
if i*j>m:break
a[i*j]=0
if not i%j:break

T=int(input())
for o in range(0,T):
n=int(input())
h,k=1,0
for i in prime:
if h*i>n:break
h*=i
k+=1
f=[1]
for i in range(1,k+1):
f.append(f[i-1]*(prime[i-1]+1))
g=math.gcd(h,f[k])
print(h//g,end='/')
print(f[k]//g)