组合数取模(comb)

【问题描述】
计算C(m,n)mod 9901的值
【输入格式】
从文件comb.in中输入数据。
输入的第一行包含两个整数,m和n
【输出格式】
输出到文件comb.out中。
输出一行,一个整数
【样例输入】
2 1
【样例输出】
2

【数据规模与约定】
对于 20%的数据,n<=m<=20
对于 40%的数据,n<=m<=2000
对于 100%的数据,n<=m<=20000

题解:组合数取模(comb)
对于 20%数据:m<=20,直接计算最后取模。
对于 40%数据:m<=2000,预处理 1~2000 的逆元,暴力计算。
对于 100%数据:m<=20000,使用 lucas 定理把缩小至 9901 以内,再用上一个方
法计算。

求组合数直接算阶乘肯定是不行的,会爆。(不能边算边mod,做除法是会出错)递推太慢了,舍弃。那么怎么办呢?只好又回去考虑,既然一定要取模,那么自然就想到一些在取模意义上相等的算法,要解决除法问题就剩下逆元(在模意义下将除法转为乘法)了。
逆元求法较多,下面提供几种:
(取模意义下除法 ->( a 除以 b )mod 一个数)
1.扩展欧几里得

inline long long extend_gcd(long long a,long long b,long long &x,long long &y){if(a == 0 && b == 0)return -1;if(b == 0){x = 1; y = 0;return a;}long long d = extend_gcd(b, a % b, y, x);y -= a / b * x;return d;
}inline long long mod_reverse(long long a,long long n){long long d = extend_gcd(a,n,x,y);if(d == 1)return ( x % n + n ) % n;elsereturn -1;
}int main(){cin >> a >> b;long long nn = mod_reverse(b, mod);//逆元cout << a * nn % mod<< endl;return 0;
}

2.费马小定理(快速幂)

long long power_mod(long long z,long long y){long long ans = 1; z %= MOD;while( y ){if(y & 1) ans = (ans * z) % MOD;z = (z * z) % MOD;y >>= 1;}return ans;
}
int main(){cin >> t;while( t-- ){cin >> a >> b;cout << (a * power_mod(b, MOD - 2)) % MOD <<endl;}return 0;
}

3.递推求阶乘逆元
a = mod / x
b = mod % x
(a*x + b) % mod = 0
a*x % mod = -b % mod
-a % mod = b * inv(x) % mod
(mod - a) % mod = b * inv(x) % mod
(mod - a) % mod * inv(b) = inv(x)

long long inva[1000005];//1--1000005的逆元
long long MOD = 1e9 + 7, ans;int main(){ans = 1;inva[1] = 1;for(int i=2; i<=1000000; i++){inva[i] = inva[ MOD % i ] * ( -MOD / i );inva[i] = ( inva[i] % MOD + MOD ) % MOD;ans *= inva[i];ans %= MOD;}cout << ans;return 0;
}

这样一来正常的数据就可以安安稳稳地AC了。
不过这道题,还要在优化一下–>Lucas

显然有了这个公式,我们就可以把组合数限定在MOD以内。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;const int mod = 9901;LL mub[10010];
LL x, y ;void init(){//预处理阶乘mub[0] = 1;//注意0! = 1for(int i=1; i<=10000; i++){mub[i] = mub[i-1] * i % mod;}
}LL work( LL m , LL n ) {//递归方法,要爆栈已舍弃if(m == n) return 1;if(n == 1) return m;else return (work( m-1, n-1 ) + work( m-1, n )) % mod;
}inline LL extend_gcd(LL a, LL b, LL &x, LL &y){//扩展欧几里得求逆元xif(a == 0 && b == 0)return -1;if(b == 0){x = 1; y = 0;return a;}LL d = extend_gcd(b, a % b, y, x);y -= a / b * x;return d;
}inline LL mod_reverse(LL a, LL n){//规范逆元XLL d = extend_gcd(a, n, x, y);if(d == 1)return ( x % n + n ) % n;elsereturn -1;
}LL solve(LL a, LL b){if(a > b) return 0;//LL nn = mod_reverse((mub[a] * mub[(b + mod - a) % mod]) % mod, mod);return mub[b] * nn % mod;
}void to_solve(LL a, LL b){//Lucas降数据if(b < mod){solve(a, b);return;}cout << solve(a/mod, b/mod) * solve(a%mod, b%mod) << endl;
}int main(){freopen("comb.in","r",stdin);freopen("comb.out","w",stdout);LL a, b;cin >> b >> a;init();if(b < mod){printf("%lld", solve(a, b));return 0;}else{to_solve(a, b);return 0;   }
}

各种逆元求法 组合数取模 comb (组合数 Lucas)相关推荐

  1. 2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理)

    J. Ceizenpok's formula time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  2. 组合数学 —— 组合数取模

    [概述] 组合数取模,即计算组合数 ,由于 ,同余定理对除法不适用,因此需要使用别的方法来解决这个问题 常见的方法有:使用逆元对组合数取模.递推打表取模.卢卡斯定理.扩展卢卡斯定理等,这些方法应用的场 ...

  3. Codeforces 869C The Intriguing Obsession 组合数取模

    Codeforces 869C The Intriguing Obsession 思考一下人生. 这是一场物语场,而且A题直接puts("Karen")能过,我对此印象非常深.我不 ...

  4. 东北育才 DAY2组合数取mod (comb)

    组合数取模(comb) [问题描述] 计算C(m,n)mod 9901的值 [输入格式] 从文件comb.in中输入数据. 输入的第一行包含两个整数,m和n [输出格式] 输出到文件comb.out中 ...

  5. java乘法逆元与除法取模,关于数论乘法逆元及相关知识点

    在求解a/b%m时,可以转化为(a%(b*m))/b,转化过程如下 令k = (a/b)/m(向下取整), x = (a/b)%m; a/b = k*m + x (x < m); a = k*b ...

  6. 数学--数论--HDU 4675 GCD of Sequence(莫比乌斯反演+卢卡斯定理求组合数+乘法逆元+快速幂取模)

    先放知识点: 莫比乌斯反演 卢卡斯定理求组合数 乘法逆元 快速幂取模 GCD of Sequence Alice is playing a game with Bob. Alice shows N i ...

  7. 组合数学 —— 组合数取模 —— 逆元与递推打表

    [逆元求法] 1.要求:p 是质数 2.时间复杂度:O(n) 3.求解  的步骤: 1)通过循环,预先算好所有小于 N 的阶乘(%p)的结果,存到数组 fac[] 中 (fac[i] = i!%p) ...

  8. 大数组合数取模(逆元+打表)

    将阶乘O(n)打表之后C(n,m)便可O(1)求出,除法取模用逆元解决 hdu5698瞬间移动 #include<bits/stdc++.h> using namespace std; c ...

  9. 组合数学 —— 组合数取模 —— 卢卡斯定理与扩展卢卡斯定理

    [卢卡斯定理] 1.要求:p 是质数,m.n 很大但 p 很小 或者 n.m 不大但大于 p 2.定理内容 其中, 3.推论 当将 n 写成 p 进制:,将 m 写成 p 进制: 时,有: 4.实现 ...

  10. 组合数取模 Lucas定理

    对于C(n, m) mod p.这里的n,m,p(p为素数)都很大的情况.就不能再用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式递推了. 这里用到Lusac定理 ...

最新文章

  1. head first python 第二版 中文版-Head First Python 中文版
  2. 阿里云服务器 宝塔面板 配置Python项目
  3. 李永乐线性代数手写笔记-二次型
  4. @ModelAttribute运用详解
  5. HDU 1010 Tempter of the Bone DFS(奇偶剪枝优化)
  6. selenium实现登录百度(自动识别简单验证码)
  7. printdocument python_python学习笔记之wxpython打印预览
  8. 传输层协议(6):TCP 连接(下-3)
  9. wsdl文件怎么看服务器地址,wsdl文件 服务器地址
  10. AutoCAD自动标注坐标和坐标输出宏
  11. 用户增长:APP推广的五大方法
  12. PHP开发工具phpDesigner 7 (最新版,含注册机)
  13. 方差 标准差_标准差和标准误的区别是什么?计算统计学方差的时候,为什么总要除以样本数?...
  14. 手机就能申请摇号 杭州市小客车摇号功能全新上线
  15. 软件测试之弱网测试工具
  16. Json使用详解(配合Ajax异步请求)
  17. 女神节礼物送什么好?女神节送女生的礼物推荐
  18. Pandas 基础(16) - Holidays
  19. PHP根据汉字转换拼音
  20. 1.Azure虚拟机部署

热门文章

  1. 利用html简单自我介绍案例
  2. Python爬虫实战,requests模块,Python实现拉勾网求职信息数据分析与可视化
  3. 小智机器人有初中课程吗_张小智
  4. 微信网页扫码登录的实现
  5. ROS编译ORB-SLAM2或其各种变种的算法遇到的编译问题
  6. 网站QQ客服直接临时会话
  7. 分享一个能对java代码进行“tokenize”的python库
  8. 装饰器模式Decorate
  9. iMovie 6 IDVD : The Missing Manual
  10. Xcode6使用iOS7模拟器调试的方法