acwing算法基础之数学知识--求组合数进阶版

目录

  • 1 基础知识
  • 2 模板
  • 3 工程化

1 基础知识

请明确如下关于取余的基本定理:

  1. 数a和数b的乘积模上p,等于数a模上p和数b模上p的乘积。即,
    ( a ⋅ b ) m o d p = ( a m o d p ) ⋅ ( b m o d p ) (a \cdot b ) \ mod \ p = (a \ mod \ p) \cdot (b \ mod \ p) (ab) mod p=(a mod p)(b mod p)
  2. 数a除以数b的结果模上p,并不等于数a模上p除以数b模上p。即,
    ( a / b ) m o d p ≠ ( a m o d p ) / ( b m o d p ) (a/b)\ mod \ p \neq (a \ mod \ p) / (b \ mod \ p) (a/b) mod p=(a mod p)/(b mod p)

(一)
题目要求:求组合数模上p的结果,即
C n k m o d p = ? C_n^k \ mod\ p =? Cnk mod p=?
其中 p = 1 e 9 + 7 p=1e9+7 p=1e9+7,是一个质数。

重新考虑组合数 C n k C_n^k Cnk的计算公式,
C n k m o d p = n ! k ! ⋅ ( n − k ) ! m o d p C_n^k \ mod \ p=\frac{n!}{k!\cdot (n-k)!} \ mod \ p Cnk mod p=k!(nk)!n! mod p
记数 k ! k! k!模p的乘法逆元为x,数 ( n − k ) ! (n-k)! (nk)!模p的乘法逆元为y,则上式可写成,
n ! k ! ⋅ ( n − k ) ! m o d p = n ! ⋅ x ⋅ y m o d p = ( n ! m o d p ) ⋅ ( x m o d p ) ⋅ ( y m o d p ) \frac{n!}{k!\cdot (n-k)!} \ mod \ p=n! \cdot x\cdot y \ mod \ p=(n! \ mod \ p)\cdot (x \ mod \ p) \cdot (y \ mod \ p) k!(nk)!n! mod p=n!xy mod p=(n! mod p)(x mod p)(y mod p)
那么,考虑数 k ! k! k!模p的乘法逆元x,由于p是质数,故x可由下式计算,
x m o d p = ( k ! ) p − 2 m o d p x \ mod\ p = (k!)^{p-2} \ mod \ p x mod p=(k!)p2 mod p
观察可以推导出其递推公式,
( k ! ) p − 2 m o d p = ( ( k − 1 ) ! ) p − 2 ⋅ k p − 2 m o d p (k!)^{p-2} \ mod \ p = ((k-1)!)^{p-2}\cdot k^{p-2} \ mod \ p (k!)p2 mod p=((k1)!)p2kp2 mod p
而对于 k p − 2 m o d p k^{p-2}\ mod \ p kp2 mod p,可以快速幂在 O ( l o g N ) O(logN) O(logN)时间复杂度下求解。

故综合上述,可以预处理出阶乘和阶乘的逆元,那么答案可以表示如下,
f a c t [ n ] ⋅ i n f a c t [ k ] ⋅ i n f a c t [ n − k ] m o d p fact[n] \cdot infact[k] \cdot infact[n-k] \ mod \ p fact[n]infact[k]infact[nk] mod p
将上述过程,用代码表述如下,

const int N = 1e5 + 10, mod = 1e9 + 7;
int fact[N], infact[N];int qmi(int a, int k, int p) {long long res = 1;while (k) {if (k & 1) {res = res * a % p;} k >>= 1;a = (long long)a * a % p;}return res;
}void init() {fact[0] = infact[0] = 1;for (int i = 1; i < N; ++i) {fact[i] = (long long)fact[i-1] * i % mod;infact[i] = (long long)infact[i-1] * qmi(i, mod - 2, mod) % mod;}return;
}

(二)
题目要求:
C n k m o d p = ? C_n^{k} \ mod \ p = ? Cnk mod p=
其中 n n n k k k的数据范围在 1 0 18 10^{18} 1018之内,而 p p p是质数,且它的范围在 1 0 6 10^6 106以内。

对于上述特别大的组合数求解,一般引入Lucas定理。

Lucas定理:当模数p是质数时,有以下等式成立,
C n k m o d p = C n m o d p k m o d p ⋅ C n / p k / p m o d p C_n^k \ mod \ p =C_{n \ mod \ p} ^ {k \ mod \ p } \cdot C_{n/p}^{k/p} \ mod \ p Cnk mod p=Cn mod pk mod pCn/pk/p mod p
其中 k m o d p k\ mod\ p k mod p n m o d p n\ mod\ p n mod p p p p以内的数,可直接计算组合数 C n m o d p k m o d p C_{n\ mod\ p}^{k \ mod \ p} Cn mod pk mod p;而对于 C n / p k / p C_{n/p}^{k/p} Cn/pk/p,则递归使用Lucas定理计算。

故,代码如下所示,

int qmi(int a, int k, int p) {long long res = 1;while (k) {if (k & 1) res = res * a % p;k >>= 1;a = (long long)a * a % p;}return res;
}int C(int a, int b, int p) {if (b > a) return 0; //无效值,返回0long long res = 1;for (int i = 1, j = a; i <= b; ++i, --j) {res = res * j % p;res = res * qmi(i, p - 2, p) % p;}return res;
}int Lucas(long long a, long long b, int p) {if (a < p && b < p) return C(a, b, p); //终止条件return (long long)C(a % p, b % p, p) * Lucas(a / p, b / p, p) % p;
}

(三)
题目要求:
C n k = ? C_n^k=? Cnk=?
此处不模上数p了,且 n n n k k k的数据范围在 1 0 4 10^4 104以内。

上式可以写成,
C n k = n ! k ! ⋅ ( n − k ) ! C_n^k=\frac{n!}{k!\cdot (n-k)!} Cnk=k!(nk)!n!
考虑任意一个数 a a a的阶乘 a ! a! a!的分解质因子,
a ! = p 1 α 1 ⋅ p 2 α 2 ⋯ p k α k a!=p_1^{\alpha_1}\cdot p_2^{\alpha_2}\cdots p_k^{\alpha_k} a!=p1α1p2α2pkαk
对于 α i \alpha_i αi,其中 0 ≤ i ≤ k 0\leq i \leq k 0ik,可以通过如下式快速计算,
α i = ⌊ a p i ⌋ + ⌊ a p i 2 ⌋ + ⌊ a p i 3 ⌋ + ⋯ \alpha_i=\lfloor \frac{a}{p_i} \rfloor + \lfloor \frac{a}{p_i^2} \rfloor + \lfloor \frac{a}{p_i^3} \rfloor + \cdots αi=pia+pi2a+pi3a+
那么,可以快速求解出 C n k C_n^k Cnk的分解质因子,然后利用高精度乘法将它们相乘即可。

代码如下,

#include <iostream>
#include <vector>using namespace std;const int N = 5010;
int primes[N], cnt;
bool st[N];
int sum[N];void get_primes(int n) {//求n以内的质数for (int i = 2; i <= n; ++i) {if (!st[i]) {primes[cnt++] = i;}for (int j = 0; primes[j] <= n / i; ++j) {st[i * primes[j]] = true;if (i % primes[j] == 0) break;}}return;
}int get(int a, int p) {//求a!中质因子p的幂int res = 0;while (a) {res += a / p;a /= p;}return res;
}vector<int> mul(vector<int> a, int b) {vector<int> c;int t = 0;for (int i = 0; i < a.size() || t; ++i) {if (i < a.size()) {t = t + a[i] * b;}c.emplace_back(t % 10);t /= 10;        }while (c.size() > 1 && c.back() == 0) {c.pop_back();}return c;
}int main() {int a, b;cin >> a >> b;get_primes(a);for (int i = 0; i < cnt; ++i) {int p = primes[i];sum[i] = get(a, p) - get(b, p) - get(a - b, p);}vector<int> res = {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];}cout << endl;return 0;
}

2 模板

暂无。。。

3 工程化

暂无。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/186599.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字系列——数字经济

数字经济是全球经济未来发展方向&#xff0c;正在成为重组全球要素资源、重塑全球经济结构、改变全球竞争格局的关键力量。都知道数字经确实很重要&#xff0c;但有些人还傻傻搞不懂数字经济到底是什么&#xff1f;小编今天就给大家捋一捋。 什么是数字经济&#xff1f; 数字经…

Glove学习笔记

global vectors for word representation B站学习视频 1、LSA与word2vec 我们用我们的见解&#xff0c;构建一个新的模型&#xff0c;Glove&#xff0c;全局向量的词表示&#xff0c;因为这个模型捕捉到全局预料的统计信息。 LSA:全局矩阵分解word2vec&#xff1a;局部上下文…

全国最大液冷数据中心全链基地

10月27日&#xff0c;曙光数创于青岛举办“深蓝计划”新品发布会暨曙光数创(青岛)产业创新基地启动仪式。会上曙光数创发布新一代一体化风液混冷先进数据中心&#xff0c;并宣布全国规模最大的液冷数据中心全链条产业创新基地正式启动。 “曙光数创希望通过全场景可用、全行业适…

AI生成的图片有版权了

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 把发到小红书的AI图片搬运到百家号&#xff0c;然后被起诉了! 长知识了&#xff0c;原来AI生成的图片也有版权了&#xff0c;AI生成图片著作权第一案判了&#xff0c;这绝对是一件划时代事情&…

微信小程序真机调试技巧,解决各种疑难杂症

1.在真机上看log 也许你调试的时候&#xff0c;会使用到真机调试或者预览模式或者体验版模式&#xff0c;这些模式都有可能出现意想不到的bug问题&#xff0c;这时候调试模式就非常非常重要了&#xff0c;特别是给领导看的时候&#xff0c;在领导手机上出现bug了&#xff0c;这…

QT 项目中添加文件夹(分类文件)

为了更方便的整理项目的文件&#xff0c;添加文件夹把文件进行分类。 1.首先在项目文件中创建新的文件夹 2.把需要归类的文件放入新建的文件中 3.右键然后选择add..... 4.运行此程序&#xff0c;会报错因为文件路径改变了&#xff0c;需要在.pro中修改路径 注意事项 文件夹内部…

NSSCTF第14页(2)

[UUCTF 2022 新生赛]ezpop 提示说看看反序列化字符串逃逸 PHP反序列化字符串逃逸_php反序列化逃逸-CSDN博客 php反序列化字符逃逸_php反序列化逃逸_Leekos的博客-CSDN博客 buuctf刷题9 (反序列化逃逸&shtml-SSI远程命令执行&idna与utf-8编码漏洞)_extract($_post);…

[PTP][1588v2] Delay_Resp消息

一、报文格式 0------3--------7--------11--------15--------------------------------31 |TranSpec|MsgType|Reserved1| VerPTP | MsgLength | ----------------|------------------|---------------------------------| | DomainNumber | Res…

码云配置遇到秘钥不正确

你这个就是秘钥没有和git绑定&#xff0c; 需要 git config --global user.name "你的用户名随便写" git config --global user.email "你的邮箱"

DCAMnet网络复现与讲解

距论文阅读完毕已经过了整整一周多。。。终于抽出时间来写这篇辣&#xff01;~ 论文阅读笔记放这里&#xff1a; 基于可变形卷积和注意力机制的带钢表面缺陷快速检测网络DCAM-Net&#xff08;论文阅读笔记&#xff09;-CSDN博客 为了方便观看&#xff0c;我把结构图也拿过来了。…

VS的调试

1.Visual Studio 中&#xff0c;Release、Debug、x86和x64 四个不同的概念 1&#xff09;Release 和 Debug 是编译的不同配置&#xff0c;用于控制编译器生成的代码和符号信息的方式。 Release 配置用于生成最终发布版本的代码。在 Release 模式下&#xff0c;编译器会进行各…

软考:2024年软考高级:软件工程

软考&#xff1a;2024年软考高级: 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &#xff08;1…

2023 年 IntelliJ IDEA下载、安装教程,附详细图文

大家好&#xff0c;今天为大家带来的是 2023年 IntelliJ IDEA 下载、安装教程&#xff0c;超详细的图文教程&#xff0c;亲测可用。 文章目录 1 IDEA 下载2 IDEA 安装3 IDEA 使用4 快捷键新手必须掌握&#xff1a;Ctrl&#xff1a;Alt&#xff1a;Shift&#xff1a;Ctrl Alt&a…

机械臂仿真之vrep如添加视觉传感器

基于视觉的机械臂作业任务&#xff0c;如何在vrep中加入视觉传感器&#xff0c;并获取画面&#xff1f;

认证鉴权方案

现在一般使用比较多的认证方式有四种: SessionTokenSSO单点登录OAtuth登录1.Cookie + Session 最常见的就是 Cookie + Session 认证。 Session,是一种有状态的会话管理机制,其目的就是为了解决HTTP无状态请求带来的问题。 当用户登录认证请求通过时,服务端会将用户的信息存…

【排序,直接插入排序 折半插入排序 希尔插入排序】

文章目录 排序排序方法的分类插入排序直接插入排序折半插入排序希尔插入排序 排序 将一组杂乱无章的数据按照一定规律排列起来。将无序序列排成一个有序序列。 排序方法的分类 储存介质&#xff1a; 内部排序&#xff1a;数据量不大&#xff0c;数据在内存&#xff0c;无需…

JeecgBoot低代码开发—Vue3版前端入门教程

JeecgBoot低代码开发—Vue3版前端入门教程 后端接口配置VUE3 必备知识1.vue3新特性a. https://v3.cn.vuejs.org/b.setup的用法c.ref 和 reactive 的用法d.新版 v-model 的用法e.script setup的用法 2.TypeScript基础 后端接口配置 如何修改后台项目路径 http://127.168.3.52:8…

【brpc学习实践】ParallelChannel的使用与并行请求

概览 ParallelChannel (有时被称为“pchan”)同时访问其包含的sub channel,并合并它们的结果。用户可通过CallMapper修改请求,通过ResponseMerger合并结果。ParallelChannel看起来就像是一个Channel: 支持同步和异步访问。 发起异步操作后可以立刻删除。 可以取消。 支持超…

ELFK集群部署(Filebeat+ELK) 本地收集nginx日志 远程收集多个日志

filebeat是一款轻量级的日志收集工具&#xff0c;可以在非JAVA环境下运行。 因此&#xff0c;filebeat常被用在非JAVAf的服务器上用于替代Logstash&#xff0c;收集日志信息。 实际上&#xff0c;Filebeat几乎可以起到与Logstash相同的作用&#xff0c; 可以将数据转发到Logst…

Python与ArcGIS系列(十一)SearchCursor方法

目录 0 简述1 SearchCursor检索要素2 where子句筛选3 几何令牌改进SearchCursor性能0 简述 从要素类和图层中以只读的方式进行检索,如获取GDP超过多少以上的城市列表。除此之外,可以进一步地对数据进行where筛选,以获取数据集子集;大数据量的情况下这种方式效率可能较低,…