在python中无聊的因子

时间:2016-04-22 11:00:59

标签: python algorithm

我正在努力理解并解决以下问题:

  
    

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是素数

enter image description here

现在我们可以写下:

(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

但是从我得到的输出中我认为我误解了他所写的内容。可以告诉我他告诉我什么是计算,以及如何编写他所说的代码。

2 个答案:

答案 0 :(得分:7)

这不是Wilson定理的直接应用。与它一起使用以下事实:

  • 如果n >= pn! = 0 (mod p)
  • 如果n < pn! = (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)

经过长时间的努力,我设法得到了这个解决方案,这在时间限制内给出了正确的输出。我在我的代码中计算了同样的东西,除了这段代码中的最后一行(即)从p中减去答案

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)