282842712474 发表于 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)$呢,我怎么感觉它的计算量也不低呀

sunwukong 发表于 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/默比乌斯函数

282842712474 发表于 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)

import time
import os
start=time.clock()
import math

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

#生成一个素数表的莫比乌斯表
def mobi(p):
length = len(p)
if length == 1:
    mu = ]
else:
    mu2=mobi(p)
    mu=mu2[:]
    for i in mu2:
      mu.append(-1*p*i)
return mu

#开始
l=2000000000 #上限
s=0 #统计个数
rl=int(math.sqrt(l))
rrl=int(math.sqrt(int(math.sqrt(l))))
rrrl=int(math.sqrt(int(math.sqrt(int(math.sqrt(l))))))

#生成rrl内的素数表
prime=#定义整数表
j=2
while j<=rrrl:
if prime != 0:
    m=int(rrl/j)
    for i in xrange(j,m+1):
      prime=0
    j=j+1
else:
    j=j+1
prime.sort() #从小到大重新排列(让0位于前面)
z=prime.count(0) #统计0的个数
prime=prime
#素数表生成完毕

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

for n in xrange(2,rl+1):
p=[] #n的素因子表
mu=[] #莫比乌斯表
nn=n
i=0
rn=int(math.sqrt(n))
#开始生成n的素因子表
while prime <= rn:
    if n%prime==0:
      n=n//prime
      if n%prime != 0:
      p.append(prime)
      i=i+1
    else:i=i+1
#下面这句的意思是,如果n的一个因子不能被前面的素数整除,那么这个因子就是素数。
if n>rn:
    p.append(n)
#n的素因子表p生成完毕
mu=mobi(p) #生成莫比乌斯表
for d in mu:
      s=s+d//abs(d)*psi(l,nn,abs(d))

print(s)
end=time.clock()
print(end-start)

282842712474 发表于 2014-6-26 23:27:16

我发觉主要的问题是,我想不出$psi(x,y)$的$O(\sqrt{x})$算法...求指教。

282842712474 发表于 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/

import time
start=time.clock()
import math

#主要计算函数(最后一个求和号)
def psi(x, y1, y2):
s=0
rx=int(math.sqrt(x))
if y2<= rx:
    for d in xrange(y1, y2+1):
      s=s+x//d

elif y1<=rx:
    for d in xrange(y1, rx+1):
      s=s+x//d
    p=x//rx-1
    q=x//y2
    d=0
    q1=x//(p-d+1)
    while d < p-q:
      q2=q1
      q1=x//(p-d)
      s=s+(q1-q2)*(p-d)
      d=d+1
    s=s+(y2-x//(q+1))*q

else:
    p=x//y1-1
    q=x//y2
    if p<q:
      s=(1+y2-y1)*q
    else:
      d=0
      q1=x//(p-d+1)
      while d < p-q:
      q2=q1
      q1=x//(p-d)
      s=s+(q1-q2)*(p-d)
      d=d+1
      s=s+(y2-x//(q+1))*q
      s=s+(x//(p+1)-y1+1)*(p+1)
return s

#生成一个素数表的莫比乌斯表
def mobi(p):
length = len(p)
mu=]
for i in xrange(1,length):
    mu2=mu[:]
    for j in mu2:
      mu.append(-1*j*p)
return mu

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

#生成rl内的素数表
prime=#定义整数表
j=2
while j<=rrl:
if prime != 0:
    m=int(rl/j)
    for i in range(j,m+1):
      prime=0
    j=j+1
else:
    j=j+1
prime.sort() #从小到大重新排列(让0位于前面)
z=prime.count(0) #统计0的个数
prime=prime
#素数表生成完毕

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

for n in xrange(2,rl+1):
p=[] #n的素因子表
mu=[] #莫比乌斯表
nn=n
i=0
rn=int(math.sqrt(n))
#开始生成n的素因子表
while prime <= rn:
    if n%prime==0:
      n=n//prime
      if n%prime != 0:
      p.append(prime)
      i=i+1
    else:i=i+1
#下面这句的意思是,如果n的一个因子不能被前面的素数整除,那么这个因子就是素数。
if n>rn:
    p.append(n)
#n的素因子表p生成完毕
mu=mobi(p) #生成莫比乌斯表
for d in mu:
    ll=l//(nn*abs(d))
    s=s+d//abs(d)*(psi(ll,nn//abs(d)+1,(2*nn-1)//abs(d)))

print(s)
end=time.clock()
print(end-start)

页: 1 2 [3]
查看完整版本: projectEuler 454 -- Diophantine reciprocals