找回密码
 欢迎注册
楼主: wayne

[擂台] projectEuler 454 -- Diophantine reciprocals

[复制链接]
发表于 2014-6-25 20:58:13 | 显示全部楼层
Lwins_G 发表于 2014-3-21 12:01
直接计算\[ \sum_{n=1}^{\sqrt{L}} \sum_{\begin{subarray}{cc} m=1 \\ (n,m)=1 \end{subarray}}^{n-1} \le ...

$\psi(x,y)$是$O(\sqrt(x))$的,那$\mu(d)$呢,我怎么感觉它的计算量也不低呀

点评

预处理即可。实际上只需要线性时间就可以计算出`\mu(1)`~`\mu(n)`。  发表于 2014-6-26 01:12
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2014-6-26 10:43:10 | 显示全部楼层
本帖最后由 sunwukong 于 2014-6-26 10:54 编辑

由 13#,

\(n^2=st,s \lt n \lt t\le L-n\)

设 \(s=k*a^2\),其中,\(k\) 无平方素因子,由整数分解定理可知,这个分解是唯一的。

由  \(n^2=k*a^2*t\)

得,\(t=k*b^2,n=k*a*b\),由 \(s\lt t\),得 \(a\lt b\),
由  \(t\le L-n\),得  \(k*b*(a+b)\le L\)

所以,原问题转化为

给定 \(L\) ,求满足

\(\mu(k)\not=0\)
\(k*b*(a+b)\le L\)
\(a\lt b\)

的解 \(\left(k,a,b \right)\) 的个数。

因为 \(b*(a+b)>=2*(1+2)=6\),所以 \(k\le L/6\)
所以
\[
\begin{split}
f(L)=\sum_{\begin{subarray}{cc} k=1 \\ \mu(k)\not=0 \end{subarray}}^{L/6} \sum_{b=2}^{\sqrt{L/k}} \min\left( b-1,\lfloor \frac{L}{kb} \rfloor-b \right)
\end{split}
\]

注: \(\mu(x)\) 是莫比乌斯函数 http://zh.wikipedia.org/wiki/默比乌斯函数
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2014-6-26 17:01:20 | 显示全部楼层
本帖最后由 282842712474 于 2014-6-26 17:14 编辑
Lwins_G 发表于 2014-3-21 12:01
直接计算\[ \sum_{n=1}^{\sqrt{L}} \sum_{\begin{subarray}{cc} m=1 \\ (n,m)=1 \end{subarray}}^{n-1} \le ...


刚刚写完了$O(L^{3/4})$的公式的代码,运行测试$f(10^9)$的时间为24s左右(由上次的190s到了24s)。
但是$f(10^{10})$运行了半个钟都没有结果,而运行$f(2\times 10^9)$需要75s
我觉得由于$d|n$的存在,需要分解n,两个公式其实都不止$O(N)$

$O(L^{3/4})$算法的代码如下(还是python)

  1. import time
  2. import os
  3. start=time.clock()
  4. import math

  5. #主要计算函数(最后一个求和号)
  6. def psi(l, n, d):
  7.   sum=0
  8.   for s in xrange(n//d+1, (2*n-1)//d + 1):
  9.     sum = sum + l//(n*d*s)
  10.   return sum

  11. #生成一个素数表的莫比乌斯表
  12. def mobi(p):
  13.   length = len(p)
  14.   if length == 1:
  15.     mu = [1,-p[0]]
  16.   else:
  17.     mu2=mobi(p[0:length-1])
  18.     mu=mu2[:]
  19.     for i in mu2:
  20.       mu.append(-1*p[length-1]*i)
  21.   return mu

  22. #开始
  23. l=2000000000 #上限
  24. s=0 #统计个数
  25. rl=int(math.sqrt(l))
  26. rrl=int(math.sqrt(int(math.sqrt(l))))
  27. rrrl=int(math.sqrt(int(math.sqrt(int(math.sqrt(l))))))

  28. #生成rrl内的素数表
  29. prime=[i for i in xrange(1,rrl+1)]#定义整数表
  30. j=2
  31. while j<=rrrl:
  32.   if prime[j-1] != 0:
  33.     m=int(rrl/j)
  34.     for i in xrange(j,m+1):
  35.       prime[i*j-1]=0
  36.     j=j+1
  37.   else:
  38.     j=j+1
  39. prime.sort() #从小到大重新排列(让0位于前面)
  40. z=prime.count(0) #统计0的个数
  41. prime=prime[z+1:rl]
  42. #素数表生成完毕

  43. prime.append(rl) #往素数表里边添加一个大数,避免溢出错误

  44. for n in xrange(2,rl+1):
  45.   p=[] #n的素因子表
  46.   mu=[] #莫比乌斯表
  47.   nn=n
  48.   i=0
  49.   rn=int(math.sqrt(n))
  50.   #开始生成n的素因子表
  51.   while prime[i] <= rn:
  52.     if n%prime[i]==0:
  53.       n=n//prime[i]
  54.       if n%prime[i] != 0:
  55.         p.append(prime[i])
  56.         i=i+1
  57.     else:i=i+1
  58.   #下面这句的意思是,如果n的一个因子不能被前面的素数整除,那么这个因子就是素数。
  59.   if n>rn:
  60.     p.append(n)
  61.   #n的素因子表p生成完毕
  62.   mu=mobi(p) #生成莫比乌斯表
  63.   for d in mu:
  64.       s=s+d//abs(d)*psi(l,nn,abs(d))

  65. print(s)
  66. end=time.clock()
  67. print(end-start)
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2014-6-26 23:27:16 | 显示全部楼层
我发觉主要的问题是,我想不出$psi(x,y)$的$O(\sqrt{x})$算法...求指教。

点评

`[\frac{x}{j}]`的取值只有`\mathcal{O}(\sqrt{x})`种。  发表于 2014-6-27 02:49
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2014-6-27 21:45:23 | 显示全部楼层
本帖最后由 282842712474 于 2014-6-28 00:33 编辑

终于做出来了。$f(10^{12})=5435004633092$,用时101秒!
稍后会整理代码出来。

=========================

http://spaces.ac.cn/index.php/archives/2665/

  1. import time
  2. start=time.clock()
  3. import math

  4. #主要计算函数(最后一个求和号)
  5. def psi(x, y1, y2):
  6.   s=0
  7.   rx=int(math.sqrt(x))
  8.   if y2<= rx:
  9.     for d in xrange(y1, y2+1):
  10.       s=s+x//d
  11.   
  12.   elif y1<=rx:
  13.     for d in xrange(y1, rx+1):
  14.       s=s+x//d
  15.     p=x//rx-1
  16.     q=x//y2
  17.     d=0
  18.     q1=x//(p-d+1)
  19.     while d < p-q:
  20.       q2=q1
  21.       q1=x//(p-d)
  22.       s=s+(q1-q2)*(p-d)
  23.       d=d+1
  24.     s=s+(y2-x//(q+1))*q
  25.   
  26.   else:
  27.     p=x//y1-1
  28.     q=x//y2
  29.     if p<q:
  30.       s=(1+y2-y1)*q
  31.     else:
  32.       d=0
  33.       q1=x//(p-d+1)
  34.       while d < p-q:
  35.         q2=q1
  36.         q1=x//(p-d)
  37.         s=s+(q1-q2)*(p-d)
  38.         d=d+1
  39.       s=s+(y2-x//(q+1))*q
  40.       s=s+(x//(p+1)-y1+1)*(p+1)
  41.   return s

  42. #生成一个素数表的莫比乌斯表
  43. def mobi(p):
  44.   length = len(p)
  45.   mu=[1,-p[0]]
  46.   for i in xrange(1,length):
  47.     mu2=mu[:]
  48.     for j in mu2:
  49.       mu.append(-1*j*p[i])
  50.   return mu

  51. #开始
  52. l=1000000000000 #上限
  53. s=0 #统计个数
  54. rl=int(math.sqrt(l))
  55. rrl=int(math.sqrt(int(math.sqrt(l))))

  56. #生成rl内的素数表
  57. prime=[i for i in range(1,rl+1)]#定义整数表
  58. j=2
  59. while j<=rrl:
  60.   if prime[j-1] != 0:
  61.     m=int(rl/j)
  62.     for i in range(j,m+1):
  63.       prime[i*j-1]=0
  64.     j=j+1
  65.   else:
  66.     j=j+1
  67. prime.sort() #从小到大重新排列(让0位于前面)
  68. z=prime.count(0) #统计0的个数
  69. prime=prime[z+1:rl]
  70. #素数表生成完毕

  71. prime.append(rl) #往素数表里边添加一个大数,避免溢出错误

  72. for n in xrange(2,rl+1):
  73.   p=[] #n的素因子表
  74.   mu=[] #莫比乌斯表
  75.   nn=n
  76.   i=0
  77.   rn=int(math.sqrt(n))
  78.   #开始生成n的素因子表
  79.   while prime[i] <= rn:
  80.     if n%prime[i]==0:
  81.       n=n//prime[i]
  82.       if n%prime[i] != 0:
  83.         p.append(prime[i])
  84.         i=i+1
  85.     else:i=i+1
  86.   #下面这句的意思是,如果n的一个因子不能被前面的素数整除,那么这个因子就是素数。
  87.   if n>rn:
  88.     p.append(n)
  89.   #n的素因子表p生成完毕
  90.   mu=mobi(p) #生成莫比乌斯表
  91.   for d in mu:
  92.     ll=l//(nn*abs(d))
  93.     s=s+d//abs(d)*(psi(ll,nn//abs(d)+1,(2*nn-1)//abs(d)))

  94. print(s)
  95. end=time.clock()
  96. print(end-start)

复制代码

点评

赞!  发表于 2014-6-28 22:10

评分

参与人数 1威望 +6 金币 +6 贡献 +6 经验 +6 鲜花 +6 收起 理由
wayne + 6 + 6 + 6 + 6 + 6 最先给出结果,赞一个先,回头有时间了我看.

查看全部评分

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-12-22 11:34 , Processed in 0.029662 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表