我一直在尝试解决一个问题,其中解决方案归结为计算
的价值这就是我写的。如果答案超出10^9+7
,我需要打印my_answer%(10^9+7)
。
mod_val=10**9+7
current=[int(x) for x in raw_input().strip().split()]
m=current[0]-1
n=current[1]-1
hi,lo=max(m,n),min(m,n)
num_prod=1
den_prod=1
for each in xrange(1,lo+1):
den_prod=den_prod*each
num_prod=num_prod*(hi+each)
print (num_prod//den_prod)%mod_val
但是在所有计算完成后,模运算正好在底部。有没有办法我可以在代码之间的某处放置模运算以节省计算或提高性能?
答案 0 :(得分:3)
<强>事实:强>
(m + n)C n =(m + n)! /(n!m!)= (1 / n!)*((m + n)!/ m!)
查看代码:
第1行:den_prod=den_prod*each
代表(1 / n!)
第2行:num_prod=num_prod*(hi+each)
代表((m + n)!/ m!)的简化形式。
关键思想是在for
循环中使用模幂运算,然后对结果应用除法模运算。除法运算变为模和逆的乘法。最后,为了计算模逆,我们使用欧拉定理。
def mod_inv (a, b):
return pow(a, b - 2, b)
mod_val=10**9+7
current=[int(x) for x in raw_input().strip().split()]
m=current[0]-1
n=current[1]-1
hi,lo=max(m,n),min(m,n)
num_prod=1
den_prod=1
for each in xrange(1,lo+1):
den_prod = (den_prod*each) % mod_val
num_prod = (num_prod*(hi+each)) % mod_val
print (num_prod * mod_inv(den_prod, mod_val)) % mod_val
我为问题定了3种不同的解决方案。时间5000组合:(5000 C n
)其中n
从0到4999.
代码1:上面的解决方案
def mod_inv (a, b):
return pow(a, b - 2, b)
mod_val=10**9+7
hi = 5000
for lo in range(0, hi-1):
# Code 1
num_prod=1
den_prod=1
for each in xrange(1,lo+1):
den_prod = (den_prod*each) % mod_val
num_prod = (num_prod*(hi+each)) % mod_val
output = (num_prod * mod_inv(den_prod, mod_val)) % mod_val
# print output
时间1:
real 0m3.607s
user 0m3.594s
sys 0m0.011s
代码2:您提出的解决方案
mod_val=10**9+7
hi = 5000
for lo in range(0, hi-1):
# Code 2
test1 = 1
test2 = 1
for each in xrange(1,lo+1):
test1 = (test1*each)
test2 = (test2*(hi+each))
test_output = (test2 / test1) % mod_val
# print test_output
时间安排2:
real 0m25.377s
user 0m25.337s
sys 0m0.027s
代码3:scipy
解决方案
from scipy.misc import comb
hi = 5000
for lo in range(0, hi-1):
# Code 3
c = comb(hi+lo, lo, exact=True)
# print c
时间3:
real 0m36.700s
user 0m36.639s
sys 0m0.048s
def mod_inv (a, b):
return pow(a, b - 2, b)
def small_nCr (n, r, mod):
hi = max(r, (n - r))
lo = min(r, (n - r))
num_prod=1
den_prod=1
for each in range (1, lo + 1):
den_prod = (den_prod * each) % mod
num_prod = (num_prod * (hi + each)) % mod
small_c = (num_prod * mod_inv (den_prod, mod)) % mod
return small_c
def lucas (n, r, mod):
c = 1
while (n > 0 or r > 0):
ni = n % mod
ri = r % mod
if (ri > ni):
return 0
c = c * small_nCr (ni, ri, mod)
n = n / mod
r = r / mod
return c
def nCr (n, r, mod):
return lucas (n, r, mod) % mod
注意:如果模数值不是素数,则可以应用中国剩余定理。
来源: