(From:离殇灬孤狼)

这个Lucas定理是解决组合数的时候用的,当然是比较大的组合数了。比如C(1000000,50000)% mod,这个mod肯定是要取的,要不算出来真的是天文数字了。

对于一个组合数C(n,k),它等于 n! / ( k! * ( n - k)! ) 我们要求一个mod。但是我们知道的同余定理是在 + - * 这三个运算中使用的,对于除法我们不能轻易的使用同余定理。如果我们能把除数(分母)转化为一个乘法就好了,这个时候我们就用到了逆元的知识:

这就开始说逆元了:

定义:对于正整数,如果有,那么把这个同余方程中的最小正整数解叫做的逆元。

如果m是素数且GCD(a,mod)== 1,我们就直接可以用费马小定理求了。即求:a^(m-2)% mod。

用快速幂求即可。

如果还不明白逆元是个啥,我举个简单的例子来看看:

求:(24 / 3)% 5 我们可以直接观察得结果:3

但是这个只是个24,如果前面是一个很大很大的数的连乘longlong都存不下呢?我们肯定是一边乘一边求mod。在这里,我们把24对5求模,结果是4。这个4不能直接除以3再求模,一看肯定是错误的。这里我们要把这个4乘3的逆元再求模。根据刚刚说的,3的逆元为3^(5-2) = 27 (或者用扩展欧几里得exGCD(3,5,x,y)这样求出来的x就是3mod5的逆元)。然后按照刚刚说的,4 * 27 % 5 = 3 ,这就是结果了。

反正根据我的理解就是,由于除法不能使用同余定理,那么我们就把除以的这个数转化为乘法,然后用同余定理即可。

逆元如果知道了,我们继续说Lucas定理的使用。

先说一下定义:

Lucas 定理:A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]   这里的每一个数组元素表示其p进制的每一位。

则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0])。也就是说,把大组合数问题变成了一个个的小组合数。(A,B小于mod)

对于每一个小组合数,我们继续刚才的说明:n! / ( k! * ( n - k)! ) ,我们要求k!*(n - k)!的逆元。套用上面逆元的求法,再看一下下面的模板,应该就不难理解了。

Lucas定理用递归的方法,代码:

  1. LL Lucas(LL n,LL k) //Lucas定理递归
  2. {
  3. if (k == ) //递归终止条件
  4. return ;
  5. else
  6. return C(n % mod , k % mod) * Lucas(n / mod , k / mod) % mod;
  7. }

然后我们要求组合数,代码:

这里用到了快速幂,代码:

  1. LL quick_mod(LL n , LL m) //求快速幂
  2. {
  3. LL ans = ;
  4. n %= mod;
  5. while (m)
  6. {
  7. if (m & )
  8. ans = ans * n % mod;
  9. n = n * n % mod;
  10. m >>= ;
  11. }
  12. return ans;
  13. }

对于阶乘,我们可以先打一个表,运算就快很多:

  1. void getfac() //打一个阶乘表
  2. {
  3. for (int i = ; i <= ; i++)
  4. fac[i] = fac[i-] * i % mod;
  5. }

来一个大代码:(求大组合数对mod = 1000003求模)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. #define CLR(a,b) memset(a,b,sizeof(a))
  6. #define INF 0x3f3f3f3f
  7. #define LL long long
  8. LL mod = ;
  9. LL fac[+] = {,};
  10. void getfac() //打一个阶乘表
  11. {
  12. for (int i = ; i <= ; i++)
  13. fac[i] = fac[i-] * i % mod;
  14. }
  15. LL quick_mod(LL n , LL m) //求快速幂
  16. {
  17. LL ans = ;
  18. n %= mod;
  19. while (m)
  20. {
  21. if (m & )
  22. ans = ans * n % mod;
  23. n = n * n % mod;
  24. m >>= ;
  25. }
  26. return ans;
  27. }
  28. LL C(LL n , LL k) //费马小定理求逆元
  29. {
  30. if (k > n)
  31. return ;
  32. else
  33. return fac[n] * (quick_mod(fac[k] * fac[n-k] % mod , mod - )) % mod;
  34. }
  35. LL Lucas(LL n,LL k) //Lucas定理递归
  36. {
  37. if (k == ) //递归终止条件
  38. return ;
  39. else
  40. return C(n % mod , k % mod) * Lucas(n / mod , k / mod) % mod;
  41. }
  42. int main()
  43. {
  44. getfac();
  45. LL n,k;
  46. int Case = ;
  47. int u;
  48. scanf ("%d",&u);
  49. while (u--)
  50. {
  51. scanf ("%lld %lld",&n,&k);
  52. printf ("Case %d: %lld\n",Case++,Lucas(n,k));
  53. }
  54. return ;
  55. }

http://blog.csdn.net/clove_unique/article/details/54571216

【转】Lucas定理 & 逆元学习小结的更多相关文章

  1. [Lucas定理]【学习笔记】

    Lucas定理 [原文]2017-02-14 [update]2017-03-28 Lucas定理 计算组合数取模,适用于n很大p较小的时候,可以将计算简化到小于p $ \binom{n}{m} \m ...

  2. lucas定理 +证明 学习笔记

    lucas定理 p为素数 \[\dbinom n m\equiv\dbinom {n\%p} {m\%p} \dbinom {n/p}{m/p}(mod p)\] 左边一项直接求,右边可递归处理,不包 ...

  3. CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)

    Codeforces Round #258 (Div. 2) Devu and Flowers E. Devu and Flowers time limit per test 4 seconds me ...

  4. HDU3037 Saving Beans(Lucas定理+乘法逆元)

    题目大概问小于等于m个的物品放到n个地方有几种方法. 即解这个n元一次方程的非负整数解的个数$x_1+x_2+x_3+\dots+x_n=y$,其中0<=y<=m. 这个方程的非负整数解个 ...

  5. lucas 定理学习

    大致意思就是求组合数C(n , m) % p的值, p为一个偶数 可以将组合数的n 和 m都理解为 p 进制的表示 n  = ak*p^k + a(k-1)*p^(k-1) + ... + a1*p ...

  6. Lucas定理学习小记

    (1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0,m=[m/p]*p+b0其次,我们 ...

  7. Lucas定理学习(进阶中)

    (1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0,m=[m/p]*p+b0其次,我们 ...

  8. [模板] 数学基础:快速幂/乘/逆元/exGCD/(ex)CRT/(ex)Lucas定理

    方便复制 快速乘/幂 时间复杂度 \(O(\log n)\). ll nmod; //快速乘 ll qmul(ll a,ll b){ ll l=a*(b>>hb)%nmod*(1ll< ...

  9. Lucas定理学习笔记

    从这里开始 一个有趣的问题 扩展Lucas算法 一个有趣的问题 题目大意 给定$n, m, p$,求$C_{n}^{m}$除以$p$后的余数. Subtask#1  $0\leqslant m\leq ...

随机推荐

  1. Pycharm 中错误ImportError: No module named appium

    Q: Pycharm 中错误ImportError: No module named appium A: Pycharm IDE Preferences -> Project Interpret ...

  2. [原创]css设置禁止中文换行

    white-space: nowrap;   如有需要还可以设置word-break,word-wrap配合.

  3. Xshell调节字体大小和样式

    有时候没有看着字体太小的,好难受, 调节字体大小: ALT+P快捷键打开

  4. 基本操作——word中怎样同一页中放入多张图片

    可能很多人在放图片时候,碰见这种情况,习惯性的把图片拖进word,发现不能在一页上很工整的排列.很多人包括我刚开始也纳闷,怎么不能一页中放入几张图片呢,缩放也不想.下面分享一个小技巧给有缘人 以我的w ...

  5. 自编码器(autoencoder)

    今天我们会来聊聊用神经网络如何进行非监督形式的学习. 也就是 autoencoder, 自编码. 压缩与解压 有一个神经网络, 它在做的事情是 接收一张图片, 然后 给它打码, 最后 再从打码后的图片 ...

  6. java 从零开始 第三天

    2015年5月2日 51刚过一天,电脑坏了.不开心,就没有更新了 Java中的类型转换 自动类型 在 Java 程序中,不同的基本数据类型的数据之间经常需要进行相互转换.例如: , 代码中 int 型 ...

  7. (转)FMS3.5的安装使用及下载地址

    一.下载及安装 FlashMediaServer3.5官方下载地址:http://download.macromedia.com/pub/flashmediaserver/updates/3_5_2/ ...

  8. 33_为应用添加多个Activity与参数传递

    1\ 2\ 3\ 4\ 2 3

  9. #!/usr/bin/python和#!/usr/bin/env 的区别(转)

    #!/usr/bin/python和#!/usr/bin/env 的区别   #!/usr/bin/python 通常在一个.py文件开头都会有这个语句 它只在Linux系统下生效,意思是当作为可执行 ...

  10. iOS 基本数据类型 和 指针 特点

    基本数据类型 : 整型int, 字符型char , 浮点型 (float 和 double), 枚举型; -- 构造类型 : 数组类型, 结构体类型, 共用体类型; -- 指针类型 : 最终要的数据类 ...