组合数的几种球阀 By cellur925
先来了解几个概念:排列数,组合数。
一、定义及有用的性质
排列数:从n个不同元素中依次取出m个元素排成一列的方案数。P(n,m)=n!/(n-m)!
组合数:从n个不同元素中依次取出m个元素形成一个集合的方案数。(注意,集合满足无序性,这是和排列数的区别)。C(n,m)=n!/m!(n-m)!
组合数性质
性质1 C(n,m)= C(n,n-m)
性质2 C(n,m)=C(n-1,m-1)+C(n-1,m)
性质3 C(n,0)+C(n,1)+C(n,2)+...+C(n,n)=2^n(道出组合数与杨辉三角间的联、系)
二、组合数球阀
① 递推 复杂度为n²
c[i][j]=c[i-1][j]+c[i-1][j-1]
但是要注意要命的初始化--

丢一段代码跑。

② 预处理阶乘+逆元 复杂度为nlogn
首先我们应该知道,除以一个数等于乘上这个数的逆元,那么我们就可以直接(生猛 地利用原始带有阶乘的公式,分母我们处理逆元。这里用到的是最简单的费马小定理方法,一个数x在膜p意义下的逆元等于x^(p-2)
丢一段代码跑。这个方法的使用条件是p为素数!
#include<cstdio>
#include<algorithm> using namespace std;
typedef long long ll;
const int p=1e9+; ll n,k,x;
ll ans=; ll ksm(ll a,ll b)
{
ll tmp=;
while(b)
{
if(b&) tmp=tmp*a%p;
b>>=;
a=a*a%p;
}
return tmp;
} int main()
{
//求C(n,k)
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) ans=ans*i%p;
for(int i=;i<=k;i++) ans=ans*ksm(i,p-)%p;
for(int i=;i<=n-k;i++) ans=ans*ksm(i,p-)%p;
printf("%lld",ans);
return ;
}
*Update 费马小定理有的时候可能会复杂度爆炸 这里介绍一种exgcd求逆元的方法
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==)
{
x=;
y=;
return a;
}
int gu=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return gu; } ll niyuan(ll hu)
{
x=,y=;
ll tmp=exgcd(hu,p,x,y);
return (x+p)%p;
} ll C(ll k,ll m)
{
ll up=fac[k]%p;
ll down=fac[m]%p*fac[k-m]%p;
ll ans=up*niyuan(down)%p;
return ans;
}
③ 分解质因数 复杂度为nlogn
前导芝士:算术分解定理。
我们把分子分母都进行分解质因数,把整个分子分母对应的质因数的指数相减(消去)
丢一段代码跑。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,m;
int p;
int i,j;
int tot;
int prim[],cnt[];
bool flag[]; void fj(int a,int k)//分解质因数 k=1/-1
{//k==1时为分子操作 质因子数++
//k==-1时为分母操作 质因子数--
int x=a;
for (int i=;i<=tot;i++)
{
if (x%prim[i]==)
{
while (x%prim[i]==) x/=prim[i],cnt[prim[i]]+=k;
}
if (x==) break;
if (prim[i]*prim[i]>n) break;
}
if (x>) cnt[x]+=k;
} int Pow(int x,int a)
{
int ans=; int j=;
while (j<=a)
{
if (j&a) ans=((LL)ans*(LL)x)%p;
j<<=;
x=((LL)x*(LL)x)%p;
}
return ans;
} int main()
{
scanf("%d%d%d",&n,&m,&p);
//筛素数
for (i=; i<=n; i++)
{
if (!flag[i]) prim[++tot]=i;
for (j=; j<=tot; j++)
{
if (prim[j]*i>n) break;
flag[prim[j]*i]=;
if (i%prim[j]==) break;
}
}
//printf("/////");
int a=m; int b=(n-m);
int c=max(a,b);
//一定有一部分会自己消去(上下完全相同)
for (i=c+; i<=n; i++)
{//分子操作
fj(i,);
}
//分母操作
for (i=;i<=min(a,b);i++) fj(i,-);
int ans=;
for (i=; i<=n; i++)
{
if (cnt[i]>) ans=((LL)ans*Pow(i,cnt[i]))%p;
}
printf("%d\n",ans);
return ;
}
组合数的几种球阀 By cellur925的更多相关文章
- 浅谈Floyd的三种用法 By cellur925
Floyd大家可能第一时间想到的是他求多源最短路的n³算法.其实它还有另外两种算法的嘛qwq.写一发总结好了qwq. 一.多源最短路 放段代码跑,注意枚举顺序,用邻接矩阵存图.本质是一种动规. 复杂度 ...
- Adjacent Bit Counts(01组合数)
Adjacent Bit Counts 4557 Adjacent Bit CountsFor a string of n bits x 1 , x 2 , x 3 ,..., x n , the a ...
- [数]数学系列预习->补水题ver.
---恢复内容开始--- 话说要学反演了,contest一题都搞不定,整理题目暂且搁置,数学笨蛋来学一下数学_(:з」∠)_ ---恢复内容结束--- 是的,预习看了半天教学,没有整理,做题又都不会, ...
- java小程序(课堂作业02)
1,三种方法计算组合数 ①设计思路:第一种方法就是通过阶乘公式然后运用公式计算出组合数,第二种通过公式推导出cnk=n/(n-k)cnk-1,然后然后从ckk 开始运算到cnk,第三种方法就是通过递归 ...
- 一种递推组合数前缀和的Trick
记录一下一种推组合数前缀和的方法 Trick 设\(\sum_{i = 0}^m C_n^i = S(n, m)\) \(S\)是可以递推的 \(S(n, m + 1) = S(n, m) + C_{ ...
- 1-求组合数(c(n, m))的几种方法
1.求C(n, m) 动态规划(递归+记忆数组) 递推关系为:C(n, m) = C(n-1, m) + C(n - 1, m - 1),C(n, m)表示为从n个数中选出m个出来,可以基于最后一个元 ...
- 组合数C(n,m)的四种求解方法
转自:文章 1.暴力求解 C(n,m)=n*(n-1)*...*(n-m+1)/m!,(n<=15): int CF(int n,int m) { ,i,j; ;i--) ans*=i; ;i- ...
- LCM性质 + 组合数 - HDU 5407 CRB and Candies
CRB and Candies Problem's Link Mean: 给定一个数n,求LCM(C(n,0),C(n,1),C(n,2)...C(n,n))的值,(n<=1e6). analy ...
- 计算一维组合数的java实现
背景很简单,就是从给定的m个不同的元素中选出n个,输出所有的组合情况! 例如:从1到m的自然数中,选择n(n<=m)个数,有多少种选择的组合,将其输出! 本方案的代码实现逻辑是比较成熟的方案: ...
随机推荐
- React学习及实例开发(三)——用react-router跳转页面
本文基于React v16.4.1 初学react,有理解不对的地方,欢迎批评指正^_^ 一.定义路由 1.安装react-router npm install react-router@ --sav ...
- The Doors--poj1556(最短路+判断点与线段的关系)
http://poj.org/problem?id=1556 题目大意:从(0,5)走到(10,5)走的最短距离是多少 中间有最多18个隔着的墙 每个墙都有两个门 你只能从门通过 我的思路是 只 ...
- Java面试题总结之Java基础(三)
1.JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try 块中可以抛出异常吗? 答:Java 通过面向对象的方法进行异常处理, ...
- 使用nginx代理weblogic负载方案
之前一直用apache来做weblogic的前端,由于nginx对静态内容的出色性能,不得不转投nginx.这里就不 再写weblogic的安装了. 安装nginx nginx需要pcre做支持,一般 ...
- 【转】c++内存管理学习纲要
http://blog.csdn.net/zhanghefu/article/details/5003407 转自:http://blog.csdn.net/wdzxl198/article/deta ...
- 【独立开发人员er Cocos2d-x实战 008】BMFont生成位图字体工具和Cocos2dx使用载入fnt文件
1.首先我们须要下载而且安装BMFont工具,下载地址例如以下:http://download.csdn.net/detail/chenqiai0/8899353(里面还有具体的使用文档,假设使用中有 ...
- Deepin-安装(读写文件)权限
在安装NODE管理模块N时,遇到了权限问题 1.给予程序读写权限(仅限文件夹) 查看权限:ls -l 或 ls 添加权限: 示例:chmod +rw xx 实例:chmod +rw node 关于权限 ...
- android事件分发(二)
非常早之前写过一篇android事件分发的博客,主要写的是它是怎样分发的,具体非常多原理的东西都没有涉及到.今天就从源代码看android怎样控制它的分发机制. 鉴于手机屏幕的限制,所以android ...
- Codeforces 344B Simple Molecules
#include<bits/stdc++.h> using namespace std; int main() { int a,b,c; scanf("%d%d%d", ...
- HDU 5285 wyh2000 and pupil(dfs或种类并查集)
wyh2000 and pupil Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Other ...