我正在努力理解并解决以下问题:
Sameer和Arpit想要克服他们对数学的恐惧,因此他们最近一直在练习数学问题。阿曼,他们的朋友 一直在帮助他们。但事实上,Sameer和Arpit已经得到了 厌倦了涉及阶乘的问题。原因是,阶乘 在问题中太容易计算,因为它们只需要残留物 模数一些素数,这很容易在线性时间内计算。所以 为他们制造有趣的东西,Aman - The Mathemagician,给他们 一个有趣的任务。他给了他们一个素数P和一个整数N. 接近P,并要求他们找到N! modulo P.他问这样的问题。
输入:
第一行包含一个整数T,即询问的查询数。
下一行T行包含“N P”形式的T查询。 (引用 清晰度)
输出:
准确输出T行,包含N!模数P.
Example Input: 3 2 5 5 11 21 71 Output: 2 10 6 Constraints: 1 <= T <= 1000 1 < P <= 2*10^9 1 <= N <= 2*10^9 Abs(N-P) <= 1000
现在我写了一个解决方案:
def factorial(c):
n1=1
n2=2
num=1
while num!=c:
n1=(n1)*(n2)
n2+=1
num+=1
return n1
for i in range(int(raw_input())):
n,p=map(int,raw_input().split())
print factorial(n)%p
但你可以看到这是一个效率低下的解决方案,所以我开始寻找一个更好的解决方案,而不是我知道这可以用wilson和fermet定理来解决。但是我无法理解作者试图说的是什么 他说:
**在数论中,威尔逊定理表明自然数n>当且仅当
时,1是素数现在我们可以写下:
(p-1)! ≡ -1 (mod p)
1*2*3*.........*(n-1)*(n)*..............*(p-1) ≡ -1 (mod p)
n!*(n+1)*...........*(p-1) ≡ -1 (mod p)
n! ≡ -1*[(n+1)*...............(p-2)*(p-1)]^-1 (mod p)
let a=[(n+1)*...............(p-2)*(p-1)]
so
n!≡-1*a^-1(mod p)
From Fermat's Theorem:
a^(p-1) ≡ 1(mod p)
multiply both side by a^-1
a^(p-2) ≡ a^-1(mod p)
now simply we have to find a^(p-2) mod p
**
所以我实现了这个:
def factorial1(n,p): # to calculate a=[(n+1)*...............(p-2)*(p-1)]
n0=n+1
n1=n0+1
while n1<=(p-1):
n0=n1*n0
n1+=1
return n0
# print nf(2,5)
for i in range(10):
n,p=map(int,raw_input().split())
if n>p:
print 0
elif n==p-1:
print p-1
else:
print (factorial1(n,p)**(p-2))%p #a^(p-2) mod p
但是从我得到的输出中我认为我误解了他所写的内容。可以告诉我他告诉我什么是计算,以及如何编写他所说的代码。
答案 0 :(得分:7)
这不是Wilson定理的直接应用。与它一起使用以下事实:
n >= p
则n! = 0 (mod p)
n < p
则n! = (p-1)!/[(n+1)(n+2)..(p-1)]
。现在使用(p-1)! = -1 (mod p)
的事实。所有剩下的就是modular multiplicative inverse(例如,使用extended Euclidean algorithm)数字n+1, n+2, ... , p-1
,这个数字最多1000
来自{{1} }}。将abs(n-p) <= 1000
乘以数字(p-1)! = -1 (mod p)
的所有模乘法逆,得到答案。 (正如约翰科尔曼所指出的那样,你也可以对产品进行逆转而不是逆向乘积作为优化)在你的情况下n+1, n+2, ... , p-1
(只是为了看它是如何运作的)
n=2, p=5
答案 1 :(得分:0)
for i in range(int(raw_input())):
n,p=map(int,raw_input().split())
if n>=p:
print 0%p
elif n==p-1:
print p-1
else:
n0=n+1
n1=n0+1
while n1<=(p-1):
n0=n1%p*n0%p
n1+=1
print p-pow(n0,(p-2),p)