有没有更好的方法来解决这个幂等方程(模n环)?

时间:2013-05-06 23:04:13

标签: python algorithm optimization idempotent

这是Project Euler的一个问题:

  

如果我们计算^ 2 mod 6为0< = a< = 5,我们得到:0,1,4,3,4,1。

     

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

     

找到M(n)为1< = n< = 10 ^ 7。

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

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提供了最小的增加,脱壳皮肤加速了大约7倍,但是当大量出现时会产生错误,pypy加速最多(大约20-30倍的速度)。但即便如此,它仍然不足以满足它必须经历的案件数量。

编辑:

我添加了

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

这预先生成了a的所有正方形,这样我就不必一遍又一遍地生成相同的正方形。程序变得稍快但仍然不够

1 个答案:

答案 0 :(得分:0)

由于内存使用的原因,这可能取决于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 factor1(n) if factors[n] < 2