求组合数+取模,详解
来源:互联网 发布:吉林广电网络集团 编辑:程序博客网 时间:2024/06/05 20:07
题目大意:
在M里面取出N个数,求有多少种组合方式。
结果对23333取模。
1<=n,m<=10000
题解:
组合数
看数据就发现可以直接用杨辉三角形或者组合数公式做,应该不会超时。
1.杨辉三角形:
时间复杂度:O(M^2)
var n,m,i,j:longint; f:array[0..1,-1..10001] of longint;begin assign(input,'d.in'); assign(output,'d.out'); reset(input); rewrite(output); readln(n,m); f[0,0]:=1; for i:=1 to m do for j:=0 to i do f[i mod 2,j]:=(f[(i+1) mod 2,j]+f[(i+1) mod 2,j-1]) mod 23333; write(f[m mod 2,n]); close(input); close(output);end.
2、公式法做:
即
然后注意取模。
PS:
对于组合数公式有一个优化,
设a/b mod c=a/b * 1 mod c,然后我们假设 b*x mod c=1,这时候我们说满足这种情况的x为b的逆元,这时候a/b * 1 mod c=a/b * b*x mod c,就可以约掉b,结果为a*x mod c。
这时候组合数的中的除法,就可以转化成乘法,即
C(N,M)=n!/m!(n-m)! mod c转化成
N!* x[m!] * x[(n-m)!] mod c。
对于一个模数p,若p为素数,则
x[i!]=i!^(p-2)
时间复杂度:O(Nlog₂N)
const modn=23333;var f:array [0..1] of longint; ny:array [0..10001] of longint; i,n,m:longint;function gcd(a,b:longint):longint;begin gcd:=1; while b<>0 do begin if b mod 2=1 then gcd:=gcd*a mod modn; b:=b div 2; a:=a*a mod modn; end;end;begin assign(input,'d.in'); reset(input); assign(output,'d.out');rewrite(output); readln(m,n); f[0]:=1; ny[0]:=1; for i:=1 to n do begin f[i mod 2]:=f[(i+1) mod 2]*i mod modn; ny[i]:=gcd(f[i mod 2],modn-2); end; writeln(f[n mod 2]*ny[m] mod modn*ny[n-m] mod modn); close(input); close(output);end.
阅读全文
1 0
- 求组合数+取模,详解
- 求组合数(取模)的两种方法
- C++求组合数
- 求组合数
- 求组合数算法
- C++求组合数
- 求组合数
- C++求组合数
- 求组合数
- 求组合数
- 求组合数
- 求组合数!!!
- 求字符串组合数
- 求组合数
- 求组合数--char4
- 求组合数
- 求组合数
- 求组合数
- Java基础常识
- shell编程test命令用法
- Android开发学习——事件监听方式
- 设计模式
- 【iOS】类簇(class cluster)
- 求组合数+取模,详解
- java变量的规则
- 利用BP神经网络对语音数据进行分类
- shiro权限管理_01
- 近况总结
- 优越数
- 动态 SQL
- iosiOS消息转发机制
- 学习【OpenCV入门教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放---思维导图