随笔 - 20  文章 - 0  评论 - 73

ACM数论之旅8---组合数(组合大法好(,,• ₃ •,,) )

一道组合数与全错排的公式。

组合数并不陌生(´・ω・`)

我们都学过组合数

会求组合数吗

一般我们用杨辉三角性质

杨辉三角上的每一个数字都等于它的左上方和右上方的和(除了边界)

第n行,第m个就是,就是C(n, m) (从0开始)

电脑上我们就开一个数组保存,像这样

用递推求

 1 #include<cstdio>
2 const int N = 2000 + 5;
3 const int MOD = (int)1e9 + 7;
4 int comb[N][N];//comb[n][m]就是C(n,m)
5 void init(){
6 for(int i = 0; i < N; i ++){
7 comb[i][0] = comb[i][i] = 1;
8 for(int j = 1; j < i; j ++){
9 comb[i][j] = comb[i-1][j] + comb[i-1][j-1];
10 comb[i][j] %= MOD;
11 }
12 }
13 }
14 int main(){
15 init();
16 }

https://ac.nowcoder.com/acm/contest/881#question E题,另外一种求组合数。

#include<bits/stdc++.h>
#define ll long long
#define M (ll)(1e9+7)
using namespace std;
ll CM[]={};
ll Pow(ll a,ll b){ //快速幂
a%=M;
ll ans = ;
for(;b;b>>=)
{
if(b&) ans = (ans*a)%M;
a = (a*a)%M;
}
return ans;
}
ll Quk(ll a,ll b){ //快速乘
a%=M;
ll ans = ;
for(;b;b>>=)
{
if(b&) ans = (ans+a)%M;
a = (a+a)%M;
}
return ans;
}
ll C(ll m,ll n){ //n>=m
return Quk(Quk(CM[n],Pow(CM[n-m],M-)),Pow(CM[m],M-))%M;
}
ll A(ll m,ll n){ //n>=m
return Quk(CM[n],Pow(CM[n-m],M-))%M;
}
int main()
{
ll a,b;
for(int i=;i<;i++) CM[i]=Quk(CM[i-],i);
while(cin>>a>>b)
{
ll ans=C(a+b,*(a+b));
if(a) ans-=C(a-,*(a+b));
if(b) ans-=C(b-,*(a+b));
cout<<(ans+*M)%M<<endl;
}
return ;
}

需要mod是质数

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3fffffff
#define maxn 100005
typedef long long ll;
ll n,m,k,t;
const ll mod = 1e9+;
ll fac[maxn];
ll inv[maxn];
ll qpow(ll a, ll b)
{
ll r = , t = a;
while (b) {
if (b & )r = (r*t) % mod;
b >>= ;t = (t*t) % mod;
}
return r;
}
void init()
{
fac[] = ;
for (int i = ;i <= mmax;i++) fac[i] = fac[i - ] * 1ll * i%mod;
inv[mmax] = qpow(fac[mmax], mod - );
for (int i = mmax - ;~i;i--) inv[i] = inv[i + ] * 1ll * (i + ) % mod;
}
ll C(ll n, ll m)
{
if (m>n) return ;
if (m == n || m == ) return ;
return fac[n] * 1ll * inv[n - m] % mod*inv[m] % mod;
}
int main(){
init();
while(~scanf("%lld%lld",&n,&m))
printf("%lld\n",(C(*m+*n,n+m)+mod-(C(*m+*n,n-)+C(*m+*n,m-))%mod)%mod);
}

(PS:大部分题目都要求求余,而且大部分都是对1e9+7这个数求余)

这种方法的复杂度是O(n^2),有没有O(n)的做法,当然有(´・ω・`)

因为大部分题都有求余,所以我们大可利用逆元的原理(没求余的题目,其实你也可以把MOD自己开的大一点,这样一样可以用逆元做)

根据这个公式

我们需要求阶乘和逆元阶乘

我们就用1e9+7来求余吧

long long F[];
void init(long long p)
{
F[] = ;
for(int i = ;i <= p;i++)
F[i] = F[i-]*i % ();
}
long long inv(long long a,long long m)
{
if(a == )return ;
return inv(m%a,m)*(m-m/a)%m;
}
long long Lucas(long long n,long long m,long long p)
{
long long ans = ;
while(n&&m)
{
long long a = n%p;
long long b = m%p;
if(a < b)return ;
ans = ans*F[a]%p*inv(F[b]*F[a-b]%p,p)%p;
n /= p;
m /= p;
}
return ans;
}

代码如下:

 1 #include<cstdio>
2 const int N = 200000 + 5;
3 const int MOD = (int)1e9 + 7;
4 int F[N], Finv[N], inv[N];//F是阶乘,Finv是逆元的阶乘
5 void init(){
6 inv[1] = 1;
7 for(int i = 2; i < N; i ++){
8 inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
9 }
10 F[0] = Finv[0] = 1;
11 for(int i = 1; i < N; i ++){
12 F[i] = F[i-1] * 1ll * i % MOD;
13 Finv[i] = Finv[i-1] * 1ll * inv[i] % MOD;
14 }
15 }
16 int comb(int n, int m){//comb(n, m)就是C(n, m)
17 if(m < 0 || m > n) return 0;
18 return F[n] * 1ll * Finv[n - m] % MOD * Finv[m] % MOD;
19 }
20 int main(){
21 init();
22 }
 

acm数论之旅--组合数(转载)的更多相关文章

  1. acm数论之旅(转载) -- 逆元

    ACM数论之旅6---数论倒数,又称逆元(我整个人都倒了( ̄﹏ ̄))   数论倒数,又称逆元(因为我说习惯逆元了,下面我都说逆元) 数论中的倒数是有特别的意义滴 你以为a的倒数在数论中还是1/a吗 ( ...

  2. acm数论之旅(转载)--素数

    https://www.cnblogs.com/linyujun/p/5198832.html 前言:好多学ACM的人都在问我数论的知识(其实我本人分不清数学和数论有什么区别,反正以后有关数学的知识我 ...

  3. acm数论之旅(转载)---最大公约数与最小公倍数

    gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm     ( gcd就是gcd(a, b), ( •̀∀•́ ) ...

  4. acm数论之旅(转载) -- 快速幂

    0和1都不是素数,也不是合数. a的b次方怎么求 pow(a, b)是数学头文件math.h里面有的函数 可是它返回值是double类型,数据有精度误差 那就自己写for循环咯 LL pow(LL a ...

  5. acm数论之旅--中国剩余定理

    ACM数论之旅9---中国剩余定理(CRT)(壮哉我大中华╰(*°▽°*)╯)   中国剩余定理,又名孙子定理o(*≧▽≦)ツ 能求解什么问题呢? 问题: 一堆物品 3个3个分剩2个 5个5个分剩3个 ...

  6. acm数论之旅--欧拉函数的证明

    随笔 - 20  文章 - 0  评论 - 73 ACM数论之旅7---欧拉函数的证明及代码实现(我会证明都是骗人的╮( ̄▽ ̄)╭) https://blog.csdn.net/chen_ze_hua ...

  7. acm数论之旅--数论四大定理

    ACM数论之旅5---数论四大定理(你怕不怕(☆゚∀゚)老实告诉我)   (本篇无证明,想要证明的去找度娘)o(*≧▽≦)ツ ----------数论四大定理--------- 数论四大定理: 1.威 ...

  8. ACM数论之旅10---大组合数-卢卡斯定理(在下卢卡斯,你是我的Master吗?(。-`ω´-) )

    记得前几章的组合数吧 我们学了O(n^2)的做法,加上逆元,我们又会了O(n)的做法 现在来了新问题,如果n和m很大呢, 比如求C(n, m) % p  , n<=1e18,m<=1e18 ...

  9. ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))

    终于讲到反演定理了,反演定理这种东西记一下公式就好了,反正我是证明不出来的~(-o ̄▽ ̄)-o 首先,著名的反演公式 我先简单的写一下o( ̄ヘ ̄*o) 比如下面这个公式 f(n) = g(1) + g ...

随机推荐

  1. Windows恢复环境启动失败,重新配置WinRE

    前言 现在很多朋友追求系统镜像体积缩小,往往删除了系统镜像中C:\Windows\System32\Recovery\winre.wim这个文件,大小将近500MB,删除这个文件不会给系统造成其他影响 ...

  2. C++-POJ1995-Raising Modulo Numbers[快速幂]

    #include <cstdio> typedef long long ll; int quick_pow(ll a,ll b,ll mod){ ll ans=; ))ans=(ans*a ...

  3. 一些docker资料汇总

    安装vmtools https://blog.csdn.net/qq_37764098/article/details/95538813 挂载vm共享文件夹 https://www.cnblogs.c ...

  4. SQLServer导出查询结果带表头(标题行)

    SQLServer导出查询结果带表头(标题行) 平时我们经常会需要将SQLSERVER查询的结果复制到EXCEL文档中进行分析处理,但是有一件事很头痛,就是复制结果网格的数据到EXCEL之后,都是没有 ...

  5. mysql 1130 Navicat for MySQL 连接MySQL 8.0 出现1130错误

    可能是帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑登入MySQL后,更改"MySQL"数据库"user"表里的&q ...

  6. JS高级---一个神奇的原型链

    一个神奇的原型链 <script> var divObj=document.getElementById("dv"); console.dir(divObj); //d ...

  7. java基础之 变量

    变量是一个内存位置的名称. 1.成员变量(实例变量,属性) 成员变量就是类中的属性,当创建对象的时候,每个对象都有一份属性.一个对象中的属性就是成员变量. 2.本地变量(局部变量) 在方法内声明的变量 ...

  8. crowdfunding项目03——mapper映射错误

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'TAd ...

  9. AcWing 4. 多重背包问题

    朴素 数据范围小 //数据范围小 #include<iostream> #include<algorithm> using namespace std ; ; int n,m; ...

  10. 钉钉、钉应用(微应用和E应用)开发介绍

    钉钉,数字化新工作方式,让工作更简单 目前在钉钉的官网可以看到,超过700万家企业组织正在使用钉钉.笔者也相信,这一数字每天都在增加.获得群众的认可,也是理所当然的,体验过钉钉,就能感觉到,钉钉的考勤 ...