Python 对于较大的输入,使此程序运行得更快时遇到问题
该程序表示一个通用公式,其中Python 对于较大的输入,使此程序运行得更快时遇到问题,python,performance,math,time-complexity,Python,Performance,Math,Time Complexity,该程序表示一个通用公式,其中x=(i*k+j)%m其中k是上一个答案的值。在某种意义上,它基本上是x1=(i*x0+j)%m,和x2=(i*x1+j)%m,等等。我遇到的问题是,计算大型输入需要很长时间 考虑到这一点,我一直在考虑使用算术级数公式,例如:a+(n-1)*d),但我不确定如何在这样的程序中实现它 def calculate(i,j,m,k,n): for v in range(1,n+1): ans = (i*k + j) % m k = a
x=(i*k+j)%m
其中k
是上一个答案的值。在某种意义上,它基本上是x1=(i*x0+j)%m
,和x2=(i*x1+j)%m
,等等。我遇到的问题是,计算大型输入需要很长时间
考虑到这一点,我一直在考虑使用算术级数公式,例如:a+(n-1)*d)
,但我不确定如何在这样的程序中实现它
def calculate(i,j,m,k,n):
for v in range(1,n+1):
ans = (i*k + j) % m
k = ans
return ans
找到了最后一行
如果m
是素数,则该公式很好。
在这种情况下,你可以用这个素数进行所有的计算,
包括分区,以保持数字较小。
你只需要快速地进行指数运算i^n
。
我建议你看看里面的参考资料。
与循环的O(n)相比,这应该给您O(log(n))时间复杂度
如果m
不是素数,则上述公式中的除法很烦人。但是你也可以通过平方来计算和,做一些类似于指数的事情。观察
x1 = (i * x0 + j)
x2 = (i * x1 + j) = i * i * x0 + i * j + j
x3 = i * i * i * x0 + i * i * j + i * j + j
xn = i^n * x0 + sum(i^t for t from 0 to n - 1) * j
= i^n * x0 + (i^n - 1) / (i - 1) * j
因此,在每一步中,可以将右括号中的求和数减半。现在没有除法,所以可以在每次运算后执行模运算。
因此,您可以定义如下内容
1 + i + i^2 + i^3 + i^4 + i^5 + i^6 + … + i^(2n+1) =
(1 + i) * (1 + i^2 + i^4 + i^6 + … + i^n)
1 + i + i^2 + i^3 + i^4 + i^5 + i^6 + … + i^(2n+2) =
1 + (i + i^2) * (1 + i^2 + i^4 + i^6 + … + i^n)
在针对您的实现运行一些随机和一些不太随机的测试用例时,可以看到整个计算
找到了最后一行
如果m
是素数,则该公式很好。
在这种情况下,你可以用这个素数进行所有的计算,
包括分区,以保持数字较小。
你只需要快速地进行指数运算i^n
。
我建议你看看里面的参考资料。
与循环的O(n)相比,这应该给您O(log(n))时间复杂度
如果m
不是素数,则上述公式中的除法很烦人。但是你也可以通过平方来计算和,做一些类似于指数的事情。观察
x1 = (i * x0 + j)
x2 = (i * x1 + j) = i * i * x0 + i * j + j
x3 = i * i * i * x0 + i * i * j + i * j + j
xn = i^n * x0 + sum(i^t for t from 0 to n - 1) * j
= i^n * x0 + (i^n - 1) / (i - 1) * j
因此,在每一步中,可以将右括号中的求和数减半。现在没有除法,所以可以在每次运算后执行模运算。
因此,您可以定义如下内容
1 + i + i^2 + i^3 + i^4 + i^5 + i^6 + … + i^(2n+1) =
(1 + i) * (1 + i^2 + i^4 + i^6 + … + i^n)
1 + i + i^2 + i^3 + i^4 + i^5 + i^6 + … + i^(2n+2) =
1 + (i + i^2) * (1 + i^2 + i^4 + i^6 + … + i^n)
在针对您的实现运行一些随机和一些不太随机的测试用例时,可以看到整个计算。您能纠正示例代码中的缩进吗?Python非常依赖缩进,很难说这段代码是什么意思。Python编译器可能也会抱怨缩进不一致。将两个循环行重写为
k=(i*k+j)%m
,这将为您节省一条赋值语句。大到什么程度?@DYZ-Like n=100000000看起来这对Python来说是一个不公平的任务。C语言中的同一个程序需要2秒钟。为了澄清上述问题:例如,i=3,j=5,m=10,k=1,n=3,然后(i*k+j)%m=(3*(1)+5)%10=8(第一次迭代),(3*(8)+5)%10=9(第二次迭代),(3*(9)+5)%10=2(第三次迭代)然后程序将输出2作为其结果。您能纠正示例代码中的缩进吗?Python非常依赖缩进,很难说这段代码是什么意思。Python编译器可能也会抱怨缩进不一致。将两个循环行重写为k=(i*k+j)%m
,这将为您节省一条赋值语句。大到什么程度?@DYZ-Like n=100000000看起来这对Python来说是一个不公平的任务。C语言中的同一个程序需要2秒钟。为了澄清上述问题:例如,i=3,j=5,m=10,k=1,n=3,然后(i*k+j)%m=(3*(1)+5)%10=8(第一次迭代),(3*(8)+5)%10=9(第二次迭代),(3*(9)+5)%10=2(第三次迭代)然后程序将输出2作为结果。我不确定我的解释是否不清楚,或者是否误解了你的答案。我意识到这代表I^n,我想要I*k,即上一个术语。kth值的功率不会随着每次迭代而增加。更像这样:假设i=3,k=1,j=5和m=10,然后(i*k+j)%m=(3*(1)+5)%10=8,基于for循环的下一次迭代将是(3*(8)+5)%10=9。使用上面的程序,虽然更快会给我错误的答案output@Zaruya,您能否为所有(i,j,m,k,n)
提供特定的值,如果您认为第一个框中的公式不能正确工作,请将其翻译为Python(i**n*k+(i**n-1)/(i-1)*j)%m
@SergGr似乎我没有正确地执行程序。用这个公式,你刚才给了我答案。然而,这仍然需要一段时间的更大values@SergGr只是modpowsum函数似乎不起作用,我不确定我的解释是否不清楚,或者误解了你的答案。我意识到这代表I^n,我想要I*k,即上一个术语。kth值的功率不会随着每次迭代而增加。更像这样:假设i=3,k=1,j=5和m=10,然后(i*k+j)%m=(3*(1)+5)%10=8,基于for循环的下一次迭代将是(3*(8)+5)%10=9。使用上面的程序,虽然更快会给我错误的答案output@Zaruya,您能否为所有(i,j,m,k,n)
提供特定的值,如果您认为第一个框中的公式不能正确工作,请将其翻译为Python(i**n*k+(i**n-1)/(i-1)*j)%m
@SergGr似乎我没有正确地执行程序。用这个公式,你刚才给了我答案。然而,这仍然需要一段时间的更大values@SergGr只是modpowsum函数似乎不起作用