Algorithm 子工厂模素数(!n mod p)

Algorithm 子工厂模素数(!n mod p),algorithm,math,Algorithm,Math,有没有一种简单的方法来实现!n mod p()其中n≤ 2.∗10^8和p是素数,而p

有没有一种简单的方法来实现
!n mod p
()
其中n≤ 2.∗10^8
p
是素数,而
p<1000


程序必须快速执行,这样简单的方法就不起作用了。

有递归公式(
!n=(n-1)(!(n-1)+!(n-2))
),为什么不实现“乘法模
p
”和“加法模
p

”?

结果是
!n mod p
是周期性的,周期为
2p
。这样我们就可以计算
!n模p
!(n mod 2p)mod p
,这是我们用失调的递归公式所做的
!n=(n-1)(!(n-1)+!(n-2))

为了证明:

  • 请注意
    !(p+1)=0 mod p
    ,由紊乱的递归关系确定
  • 工作模p,
    !(n+p)=!p*!n
    (这可以通过前面的观察归纳证明)
  • 请注意
    !p=-1模p
    。维基百科提供了一个公式:
    !n=n!-求和[(n选择i)*!(n-i),i=1..n]
    --模p,右侧唯一的非零项出现在
    i=n
  • 得出结论:
    !(n+2p)=!PPn=!n mod p

从证明中,我们看到我们实际上可以计算
!n=±!(n mod p)mod p
n mod 2p
小于
p

时符号为正时,SteveJessop与链接中的符号相同吗?@Luchian:是的,子成分是紊乱的数量。@LuchianGrigore-不明显,这是它的意思。我不知道你为什么还原了我的编辑。。。显然他不想计算n mod p。如果你想删除C++标签,它与此无关。既然<代码> p<1000 <代码>,那么如果错乱是周期性的mod <代码> p<代码>,则可能值得研究。例如,前几个
1、0、1、2、9、44、265、1854、14833、133496、1334961、14684570、176214841、2290792932
是周期性的mod
2
,周期为2:奇偶。。。;我敢肯定这一点永远适用,对于其他数字也是如此!n mod p
似乎是周期性的,周期
2p
(对于奇数p),因此这提供了一个简单的算法来计算所需的值。不过,您可能想尝试证明周期性。对于
n
那么大?太慢了。@Vlad:我觉得太慢了,因为它可能需要大约400米的操作。执行时间大约是0,2秒。n乘法需要的时间太长了。我相信有一些聪明的方法可以减少这个问题,因为p限制是p<1000。@BugMeNot-这是一个非常重要的限制!请将其与任何其他信息一起添加到OP中。考虑到这一关系可能是一种有效的前进方式。如果你记忆函数
f(a,b,c){return(a-1)(b+c)%p}
,那么你最坏需要10亿个给定值
p<1000
。但是Nabb观察到上面的
!n mod p
似乎是周期性的,周期比这短,所以实际上需要的时间更少。再加上一些循环检测,您可能会很快得到值。这不需要做任何数学计算——最好提前证明一些很好的公式,比如
2*p
,来计算周期长度,但考虑到0.2s的时间限制,可能没有必要:-)