先来了解几个概念:排列数,组合数。

一、定义及有用的性质

排列数:从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的更多相关文章

  1. 浅谈Floyd的三种用法 By cellur925

    Floyd大家可能第一时间想到的是他求多源最短路的n³算法.其实它还有另外两种算法的嘛qwq.写一发总结好了qwq. 一.多源最短路 放段代码跑,注意枚举顺序,用邻接矩阵存图.本质是一种动规. 复杂度 ...

  2. 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 ...

  3. [数]数学系列预习->补水题ver.

    ---恢复内容开始--- 话说要学反演了,contest一题都搞不定,整理题目暂且搁置,数学笨蛋来学一下数学_(:з」∠)_ ---恢复内容结束--- 是的,预习看了半天教学,没有整理,做题又都不会, ...

  4. java小程序(课堂作业02)

    1,三种方法计算组合数 ①设计思路:第一种方法就是通过阶乘公式然后运用公式计算出组合数,第二种通过公式推导出cnk=n/(n-k)cnk-1,然后然后从ckk 开始运算到cnk,第三种方法就是通过递归 ...

  5. 一种递推组合数前缀和的Trick

    记录一下一种推组合数前缀和的方法 Trick 设\(\sum_{i = 0}^m C_n^i = S(n, m)\) \(S\)是可以递推的 \(S(n, m + 1) = S(n, m) + C_{ ...

  6. 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个出来,可以基于最后一个元 ...

  7. 组合数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- ...

  8. 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 ...

  9. 计算一维组合数的java实现

    背景很简单,就是从给定的m个不同的元素中选出n个,输出所有的组合情况! 例如:从1到m的自然数中,选择n(n<=m)个数,有多少种选择的组合,将其输出! 本方案的代码实现逻辑是比较成熟的方案: ...

随机推荐

  1. T1365 浴火银河星际跳跃 codevs

    http://codevs.cn/problem/1365/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 小 K 又在玩浴 ...

  2. Eclipse的JQuery提示插件-Spket(别试了,没什么效果,且安装设置麻烦)

    参考: http://www.cnblogs.com/shulin/archive/2010/08/09/1796146.html 我测试了,但是没用起来,原因有如下几点: 1.配置复杂,且提示效果不 ...

  3. ORACLE DTRACE DOC

    http://docs.oracle.com/cd/E19253-01/817-6223/

  4. linux安装mail服务使用外部MTA发送邮件

    阉割版的linux没有mail命令,也没有/etc/mail.rc文件 需要安装mail服务 yum install mailx.x86_64 几个概念:MUA.MTA.MDA 邮件用户代理(MUA, ...

  5. Meteor在手机上运行

    在本章中,我们将学习如何在Android设备上运行你的应用程序.最近Meteor刚刚添加此功能适用于Windows操作系统,所以我们需要更新 Meteor 应用到 1.3测试版. 注 在写的时候本教程 ...

  6. UVa 401 Palindromes(镜像回文字符串)

     题意  给一个字符串 判定其是否为回文串和镜像串  回文串非常好推断  镜像串对于每个字符用数组保存它的镜像字符即可了  没有的就是空格 注意若字符串长度为奇数  中间那个字母必须是对称的才是镜 ...

  7. 【iOS系列】-UIImageView帧动画相关属性介绍

    UIImageView帧动画相关属性介绍 1:相关属性: //An array of UIImage objects to use for an animation.存放UIImage对象,会按顺序显 ...

  8. Chapter 20: Diagnostics

    WHAT'S IN THIS CHAPTER?n Code contractsn Tracingn Event loggingn Performance monitoringWROX.COM CODE ...

  9. window下安装多个tomcat

    解压该压缩包,生成3分tomcat 分别命名为 tomcat1,tomcat2,tomcat3 进入tomcat1/conf/目录,修改server.xml 进入tomcat1/bin目录,修改 se ...

  10. Android连接wifi,调用系统API【转】

    本文转载自:http://blog.csdn.net/aaa1050070637/article/details/54136472 直接上代码,简单粗暴,一看就懂 import android.con ...