OJ:对质数取余小结 & Faberge easter eggs crush test [linear]

背景

很多OJ题目会涉及对一个大质数取余数。

基础知识

  • Lucas定理
    在这里插入图片描述
  • 费马小定理:如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p)
  • 快速幂:https://zhuanlan.zhihu.com/p/95902286

常见题型

  1. 幂次取余:即计算a^n mod p。用快速幂算。
  2. 组合数取余:即计算C(n, m) mod p. 使用如下策略:
  • n >= p的情况下,先使用Lucas定理,将求余的对象转成多个组合数的乘积。
  • 在转化到n, m < p之后,考虑到C(n, m) = n! / m! / (n-m)!,而根据费马小定理,m! ^ (p-1) mod p == 1, (n-m)! ^ (p-1) == 1,三者相乘可得,C(n, m)n!*(m!(n-m)!) ^ (p-2)mod p同余。因此,计算n! mod p(m!(n-m)!) ^ (p-2) mod p即可。后者可以用快速幂求,且m!(n-m)! mod p可以在求n! mod p的过程中求出。

例题

https://www.codewars.com/kata/5976c5a5cd933a7bbd000029

首先列个DP的递推式,然后计算,发现这道题的核心是求length(n, m) = C(m, 1) + ... + C(m, n).对大素数MOD的模。(好吧,实际上看样例就能猜出来通项公式。)

Step 1.

forall n < MOD,
C(m, n) = C(m//MOD, n//MOD) * C(m%MOD, n%MOD) = C(m//MOD, 0) * C(m%MOD, n) = C(m%MOD, n).
(同模MOD意义下的相等)

注意到题目条件,题目中的n < MOD必然,所以在m较大的时候,先将其转化为m对MOD的余数,即length(n, m) = length(n, m % MOD).

Step 2.

when n > m, C(m, n) = 0.

考虑到这一点,length(n, m) = length(min(n, m), m).

Step 3.

C(m, 1) = m
C(m, i+1) = C(m, i) * (m-i) / (i+1) = C(m, i) * (m-i) * (i+1) ^ (MOD-2)
(同模MOD意义下的相等)

考虑到这一点,在计算每个组合数对大素数的余数时,我们可以迭代地计算。
另外,考虑到评测系统会运行多个测试样例,为了效率,我们可以先把1 ^ (MOD-2), 2 ^ (MOD-2), ...的结果存储下来,防止在使用时进行重复计算。

执行完这三步就能通过这道题。代码不放了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值