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
是周期性的mod2
,周期为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的时间限制,可能没有必要:-)