首页 > 其他分享 >组合数的多种求法

组合数的多种求法

时间:2023-07-24 21:47:06浏览次数:28  
标签:多种 组合 int res LL 求法 逆元 mod

一、递推法[杨辉三角法]

组合数满足递推关系\(C(n, k) = C(n-1, k-1) + C(n-1, k)\)。因此,可以使用递推法计算组合数。这种方法需要预处理\(C(0, 0) = 1\)和\(C(n, 0) = 1\)以及\(C(n, n) = 1\)的边界情况,然后使用递推公式计算出其他组合数的值。
杨辉三角是一种三角形数表,其中每个数等于它上方两数之和。杨辉三角的第n行中的第k个数就是组合数C(n-1, k-1)。因此,可以使用杨辉三角来计算组合数。
特点:

  1. 时间复杂度\(O(T ^ 2)\)【T为询问次数】
  2. 递推[DP] + 注意边界处理
  3. 取模
点击查看代码
void init(){
	for(int i = 0; i < N; i ++){
		for(int j = 0; j <= i; j ++){
			if(!j)C[i][j] = 1;
			else C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
		}
	}
}

二、阶乘逆元法

阶乘逆元法是一种用于计算组合数模质数的方法。该方法使用费马小定理,将求组合数的问题转化为求阶乘逆元的问题。具体来说,如果mod是质数,那么可以先预处理出1到mod-1的阶乘逆元,然后使用这些逆元来计算组合数模mod的值。
特点:

  1. 时间复杂度\(O(TlogT)\)【T为询问次数】
  2. 预处理出阶乘和阶乘的逆元
  3. 公式法求组合数 + 快速幂求逆元 + 边界处理
  4. 取模,模一般为大质数[互质条件]
点击查看代码
typedef long long LL;
const int N = 1e5 + 10,mod = 1e9 + 7;
LL fact[N],infact[N];
LL qmi(LL a,LL k){
	LL res = 1;
	while(k){
		if(k & 1)res = res * a % mod;
		a = a * a % mod;
		k >>= 1; 
	}
	return res;
}


void init(){
	fact[0] = infact[0] = 1;
	for(int i = 1; i < N; i ++){
		fact[i] = fact[i - 1] * i % mod;
		infact[i] = qmi(fact[i], mod - 2) % mod;	//快速幂求逆元
	}
}


	//fact[a] * infact[b] % mod * infact[a - b] % mod

三、Lucas定理

Lucas定理是一个用于计算组合数模质数的定理。该定理指出,如果p是质数,n和k是非负整数,那么C(n, k)模p的值等于\(C(n\ mod\ p, k\ mod\ p)\)和\(C(n/p, k/p)\ mod\ p\)的值的乘积模p的值。Lucas定理的优点是可以避免数据溢出,并且可以使用较小的质数求解问题。
特点:

  1. 时间复杂度\(O(plogNlogp)\)【p为mod,N为组合数下标】
  2. 取模数小,组合数下标和上标n,k大
  3. lucas递归 + 定义循环求组合数 + 快速幂逆元
点击查看代码
typedef long long LL;
LL qmi(LL a,LL k,LL p){
    LL res = 1;
    while(k){
        if(k & 1)res = res * a % p;
        a = a * a % p;
        k >>= 1;
    }
    return res;
}

LL C(LL n,LL k,LL p){
    LL res = 1;
    for(int i = n,j = 1; j <= k; i --,j ++ ){
        res = res * i % p;
        res = res * qmi(j,p - 2,p) % p;
    }
    return res;
}

LL lucas(LL n,LL k,LL p){
    if(n < p && k < p)return C(n,k,p);
    else return C(n % p,k % p,p) * lucas(n/p,k/p,p) % p;
}


//lucas(n,k,p) << '\n';

四、高精度组合数

特点:

  1. 分解质因数 + 高精度乘法
  2. 不取模
  3. 阶乘里有多少个某个因子
点击查看代码
#include<iostream>
#include<vector>
using namespace std;
typedef vector<int> VI;
const int N = 5010;
int primes[N],sum[N],cnt;
bool st[N];

void get_primes(){
	for(int i = 2; i < N; i ++){
		if(!st[i])primes[cnt++] = i;
		for(int j = 0;primes[j] <= N / i;  j ++){
			st[primes[j] * i] = 1;
			if(i % primes[j] == 0)break;
		}
	}
}

int get(int n,int p){
	int res = 0;
	while(n){
		res += n / p;
		n /= p;
	}
	return res;
}

VI mul(VI A,int b){
	VI res;
	int t = 0;
	for(int i = 0; i <= A.size() -1 || t; i ++){
		if(i <= A.size() - 1)t += A[i] * b;
		res.push_back(t%10);
		t /= 10;
	}
	while(res.size() > 1 && res.back() == 0)res.pop_back();
	return res;
}

int main(){
	int a,b;
	cin >> a >> b;
	get_primes();
	for(int i = 0; i < cnt; i ++){
		int p = primes[i];
		sum[i] = get(a,p) - get(b,p) -get(a-b,p);
	}
	VI res;
	res.push_back(1);
	for(int i = 0 ;i <cnt; i ++){
		int p = primes[i];
		for(int j = 0; j < sum[i] ; j ++){
			res = mul(res,p);
		}
	}
	for(int i =res.size()-1; i>=0; i --)cout << res[i];
	return 0;
}

标签:多种,组合,int,res,LL,求法,逆元,mod
From: https://www.cnblogs.com/J-12045/p/17577889.html

相关文章

  • 持续改进数字资产组合的策略:黑客增长和 PLG 的好处
    产品引领型增长大家好,今天我将为大家介绍一种颠覆传统销售和业务增长认知的策略,它被称为”产品引领型增长“(Product-LedGrowth,简称PLG)。PLG是一种适应数字时代用户需求和行为的创新策略,它通过将产品作为核心,以用户体验和产品价值为导向,实现企业的增长和成功。如果你想了解更......
  • [TSG@Site开发日志3]从C#到Qt,再从Qt到C# 和 Qt的组合开发,浅谈在采集端工控设备开发中
    [TSG开发日志3]从C#到Qt,再从Qt到C#,浅谈不同技术之间选型的利与弊当前在South公司的开发历经了几个时代,第一个时代是用C#进行的开发,第二个时代是从C#向Qt逐渐转型,第三个时代是我现在站在十字路口上,又需要将采集端软件从Qt的路上拉回来。为什么先看看AI怎么说选择使用C#还是Qt来......
  • 组合的输出 dfs
    #include<bits/stdc++.h>usingnamespacestd;inta[101];intm,n;voids(intk){inti;if(k>m){for(i=1;i<=m;i++){cout<<setw(3)<<a[i];}cout<<endl;return;}for......
  • 宝塔面板与长亭雷池waf组合
     一、宝塔面板这边的修改1.1更改nginx目录下的全部conf文件中80端口,改为其他,假设改为801,具体conf路径看网站设置,配置文件的最后一行。(参考https://www.bt.cn/bbs/thread-107318-1-1.html)1.2、更改网站的nginx配置文件,比如将443改为4434端口。1.3、重启nginx。Servicenginxres......
  • 组合的输出
    #include<bits/stdc++.h>usingnamespacestd;intn,r,a[25];boolvis[25];voiddfs(intdep){for(inti=a[dep-1]+1;i<=n;i++){if(!vis[i]){a[dep]=i;if(dep==r){......
  • vue3组合式 API_为 computed() 标注类型
    computed() 会自动从其计算函数的返回值上推导出类型<template><h3>{{doubleCount}}</h3></template><scriptsetuplang="ts">import{ref,computed}from"vue"constcount=ref<number>(100)//推导得到的类型:ComputedRef&l......
  • vue3中组合式 API_为 reactive() 标注类型
    reactive() 也会隐式地从它的参数中推导类型<template><h3>{{book.title}}</h3><h3>{{book.author}}</h3></template><scriptsetuplang="ts">import{reactive}from"vue"constbook=reactive({title......
  • VUE|组合式API
    VUE|组合式API1setup语法糖在vue项目中,通常使用setup语法简化书写setup的特点在setup语法中定义变量,可以直接在模板中使用在setup语法中定义函数,可以直接在模板中使用导入的组件对象,可以直接在模板中使用常用的组合式APIrefcomputedwatchonMounted2ref......
  • 多类分类 多种可能 ml.net
    多类分类:多种可能的机器学习在机器学习领域,多类分类是指将数据分成多个不同类别的任务。而多种可能则是指每个类别都有多个可能的结果。在这篇文章中,我们将介绍如何使用ML.NET来进行多类分类的任务,并给出相应的代码示例。什么是多类分类?多类分类是一种将数据分成多个不同类别的......
  • 排列组合
    错排问题对于第n信,必然放在1~n-1号信封中。假设n号信放在1号信封中,考虑一号信放在哪放在n号信封中,还剩的n-2封信和信封构成了n-2的子问题f(n-2)放在k号信封(\(2\lek<n\))f(n-1)因为n可以放在n-1个位置。所以(f(n-1)+f(n-2))*(n-1)P1595信封问题板子题,不多说了P4071[SDO......