acwing算法基础之数学知识--求组合数进阶版
目录
- 1 基础知识
- 2 模板
- 3 工程化
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) (a⋅b) mod p=(a mod p)⋅(b mod p) - 数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!⋅(n−k)!n! mod p
记数 k ! k! k!模p的乘法逆元为x,数 ( n − k ) ! (n-k)! (n−k)!模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!⋅(n−k)!n! mod p=n!⋅x⋅y 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!)p−2 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!)p−2 mod p=((k−1)!)p−2⋅kp−2 mod p
而对于 k p − 2 m o d p k^{p-2}\ mod \ p kp−2 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[n−k] 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 p⋅Cn/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!⋅(n−k)!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α1⋅p2α2⋯pkαk
对于 α i \alpha_i αi,其中 0 ≤ i ≤ k 0\leq i \leq k 0≤i≤k,可以通过如下式快速计算,
α 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 工程化
暂无。。。
相关文章:
acwing算法基础之数学知识--求组合数进阶版
目录 1 基础知识2 模板3 工程化 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 …...
基础算法:大数除以除以13
基础算法:大数除以一个数 信息学奥赛:1175:除以13 时间限制: 1000 ms 内存限制: 65536 KB 【题目描述】 输入一个大于0的大整数N,长度不超过100位,要求输出其除以13得到的商和余数。 【输入】 一个大于0的大整数&…...
软件版本区分
引言 定义好版本号对于产品的版本发布与持续更新很重要但是对于版本怎么定义规则如何确定却是千差万别。具体应用可以结合自己目前的实际情况命名。另外对于商业软件有的产品号称是永远的Beta版持续不断地更新、优化迭代产品才有生命力。 ⭕ 软件版本周期 α、β、λ 常用来…...
Redis高可用之主从复制及哨兵模式
一、Redis的主从复制 1.1 Redis主从复制定义 主从复制是redis实现高可用的基础,哨兵模式和集群都是在主从复制的基础之上实现高可用; 主从复制实现数据的多级备份,以及读写分离(主服务器负责写,从服务器只能读) 1.2 主从复制流…...
代理模式,dk动态代理,cglib动态代理
目录 一、代理模式1、生活中代理案例2、为什么要使用代理3、代理模式在Java中的应用4、什么是代理模式 二、代理的实现方式1、java中代理图示2、静态代理 三、动态代理1、概述2、JDK动态代理jdk动态代理原理分析 3、Cglib动态代理3.1 基本使用3.2 cglib基本原理 一、代理模式 …...
Vue2系列 -- 组件自动化全局注册(require.context)
参考官网:https://v2.cn.vuejs.org/v2/guide/components-registration.html 1 作用 省略 import 引入组件 省略 在main.js 中注册 实现自动化引入组件 2 自定义文件夹 在 src 下新建一个 components/base 文件夹,用于存放要自动注册的组件 3 在 base…...
【华为OD题库-038】支持优先级的对列-java
题目 实现一个支持优先级的队列,高优先级先出队列,同优先级时先进先出。 如果两个输入数据和优先级都相同,则后一个数据不入队列被丢弃。 队列存储的数据内容是一个 整数。 输入描述 一组待存入队列的数据(包含内容和优先级)。 输出描述 队列…...
python爱心代码高级
在Python中,我们可以使用matplotlib库来创建一个更高级的爱心图形。以下是一个示例: import matplotlib.pyplot as pltimport numpy as npx np.linspace(-2, 2, 1000)y1 np.sqrt(1-(abs(x)-1)**2)y2 -3*np.sqrt(1-(abs(x)/2)**0.5)fig, ax plt.subp…...
基于SSM+Vue的社区共享食堂管理系统
基于SSM的社区共享食堂管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringMyBatisSpringMVC工具:IDEA/Ecilpse、Navicat、Maven 系统展示 主页 菜品详情 管理员界面 摘要 社区共享食堂管理系统是一种基于SSM…...
MYSQL基础知识之【修改数据,删除数据】
文章目录 前言MySQL UPDATE 查询使用PHP脚本更新数据 MySQL DELETE 语句从命令行中删除数据使用 PHP 脚本删除数据 后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:Mysql 🐱👓博主在前端领域还有很多知识和技术…...
【机器学习】交叉验证 Cross-validation
交叉验证(CrossValidation)方法思想简介 以下简称交叉验证(Cross Validation)为CV.CV是用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set),首先用训练集对分类器进…...
Pycharm修改文件默认打开方式 + CSV Editor插件使用
1、File —> Settings —> Editor —> File Types 然后将*csv添加到最上面 在plugins中下载插件,CSV Editor 备注:不在上一步的“File Types”中将*.csv设置为CSV格式,插件是不起作用的 就可以使用了...
shiro整合redis
shiro整合redis 前言:shiro默认的session是存储在jvm内存中的,这样会导致java服务内存占用更大以及一旦服务器宕机或者版本迭代需要重启服务时,缓存中的数据不能恢复,导致用户需要重新登录认证,体验很差。因此利用第三…...
HarmonyOS(七)——@BuilderParam装饰器
前言: 前面我们认识了Builder装饰器:自定义构建函数,今天我们继续认识下一个装饰器——BuilderParam装饰器。 当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接…...
展开运算符(...)
假如我们有一个数组: const arr [7,8,9];● 我们如果想要数组中的元素,我们必须一个一个手动的去获取,如下: const arr [7,8,9]; const badNewArr [5, 6, arr[0], arr[1],arr[2]]; console.log(badNewArr);● 但是通过展开运…...
Apache Flink(二):数据架构演变
🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹…...
【C++】类与对象(中)
一、类的默认成员函数 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会自…...
webshell之无扩展免杀
1.php加密 这里是利用phpjiami网站进行加密,进而达到加密效果 加密前: 查杀效果 可以看到这里D某和某狗都查杀 里用php加密后效果 查杀效果 可以看到这里只有D某会显示加密脚本,而某狗直接绕过 2.dezend加密 可以看到dezend加密的特征还是…...
用 VirtualBox 安装 OpenWrt 等 Linux 系统,无法启动的解决办法
用 VirtualBox 安装 OpenWrt 等 Linux 系统,无法启动的解决办法 最近新买了台联想小新 Pro 14 2023 锐龙版,因为有 32GB 的运行内存,所以想安装虚拟机以充分发挥。一开始使用 Hyper-V 来安装可以正常使用,但是后面想使用 Virtual…...
Windows下搭建Tomcat HTTP服务,发布公网远程访问
文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 前言 Tomcat作为一个轻量级的服务器,不仅名字很有趣࿰…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
