【问题标题】:Is there any more optimal way to solve this idempotent equation (modulo n ring)?有没有更优化的方法来解决这个幂等方程(模n环)?
【发布时间】:2015-01-23 01:12:06
【问题描述】:

这是 Project Euler 的问题之一:

如果我们为 0

“a”的最大值使得 a^2 mod 6 = a 为 4。 让我们称 M(n) 为 a

为 1

到目前为止,这就是我所拥有的:

import time
start = time.time()
from math import sqrt

squares=[]
for numba in xrange(0,10000001/2+2):
    squares.append(numba*numba)
def primes1(n):
    """ Returns  a list of primes < n """
    sieve = [True] * (n/2)
    for i in xrange(3,int(sqrt(n))+1,2):
        if sieve[i/2]:
            sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
    return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]


tot=0

gor = primes1(10000001)

def factor1(n):
    '''Returns whether a number has more than 1 prime factor'''
    boo = False


    '''if n in gor:
        return True'''


    for e in xrange(0,len(gor)):



        z=gor[e]    

        if n%z==0:

            if boo:
                return False
            boo = True
        elif z*2>n:  
            break
    return True

for n in xrange(2,10000001):

    if factor1(n):

        tot+=1
    else:
        for a in xrange(int(sqrt(n))+1,n/2+1):
            if squares[a]%n==a:

                tot+=n+1-a
                break

print tot
print time.time()-start

我已经在较小的情况下尝试了此代码,并且效果很好;但是,做 10^7 个案例太慢了。

目前,对于 n 小于 20000,它的运行时间约为 8 秒。 当 n 小于 90000 时,运行时间约为 150 秒。

据我所知,对于 n 小于 10^7,它会运行数小时甚至数天。

我已经在使用筛子来生成素数,以便这部分尽可能快,我可以做些什么来加快其余代码的速度吗?

我已经尝试过使用不同的编译器,例如 psyco、pypy 和 shedskin。 Psyco 提供了最小的增加,shedskin 将其加速了大约 7 倍,但在出现大量数据时会产生错误,pypy 的速度最快(大约是速度的 20-30 倍)。但即便如此,对于必须处理的案件数量来说,它仍然不够快。

编辑:

我加了

squares=[]
for numba in xrange(0,10000001/2+2):
    squares.append(numba*numba)

这会预先生成a 的所有正方形,这样我就不必一遍又一遍地生成相同的正方形。程序稍微快了一点,但还是不够

【问题讨论】:

  • 这是原来的 Project Euler 问题:projecteuler.net/problem=407
  • 当然有更好的方法。提示:你能通过使用n 的素因数分解来减少a 的候选数吗?
  • 最好在codereview.stackexchange.com上询问
  • 我可以通过使用 n 的素因子的值进行迭代来减少 a 的候选者,但是,当我测试它时,由于我必须执行额外的操作,它最终的速度大致相同。
  • 看方程式并思考。自己解决,比作弊更让人满足。

标签: python algorithm optimization idempotent


【解决方案1】:

由于内存使用情况,这可能取决于 N 的大小,但在较小的测试中,我通过预先计算因子计数发现了一些改进。所以是这样的:

factors = [0]*N
for z in gor:
  for n in xrange(1,N):
    m = z*n
    if m >= N: break
    factors[m] += 1 

N 是 10000001,或者您使用的任何计数器。

那么你可以用if factors[n] &lt; 2代替if factor1(n)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多