【模板】组合数取模

2023-10-27

1.利用递推式预处理组合数取模

题目描述

给定 n n n 组询问,每组询问给定两个整数 a , b a, b a,b,请你输出 C a b   m o d   ( 1 0 9 + 7 ) C_a^b \ mod \ (10^9+7) Cab mod (109+7) 的值。

数据范围

1 ≤ n ≤ 10000 1 \le n \le 10000 1n10000

1 ≤ b ≤ a ≤ 2000 1 \le b \le a \le 2000 1ba2000

递推式

C a b = C a − 1 b + C a − 1 b − 1 C_a^b = C_{a-1}^{b}+C_{a-1}^{b-1} Cab=Ca1b+Ca1b1

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 2010, mod = 1e9 + 7;
int c[N][N];

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;
            }
        }
    }
}

int main()
{
    init();
    
    int n;
    scanf("%d", &n);
    
    while (n--)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        printf("%d\n", c[a][b]);
    }
    
    return 0;
}

2.预处理阶乘的余数和阶乘逆元的余数

题目描述

给定 n n n 组询问,每组询问给定两个整数 a , b a, b a,b,请你输出 C a b   m o d   ( 1 0 9 + 7 ) C_a^b\ mod\ (10^9+7) Cab mod (109+7) 的值。

数据范围

1 ≤ n ≤ 10000 1 \le n \le 10000 1n10000

1 ≤ b ≤ a ≤ 1 0 5 1 \le b \le a \le 10^5 1ba105

逆元

a ∗ x ≡ 1   ( m o d   b ) a ∗ x ≡ 1 \ (mod \ b) ax1 (mod b) a a a b b b 互质,那么我们就能定义 x x x a a a 的逆元,记为 a − 1 a^{−1} a1,所以我们也可以称 x x x a a a m o d   b mod\ b mod b 意义下的倒数。

因此,对于 a b   ( m o d   p ) \frac{a}{b}\ (mod\ p) ba (mod p),我们就可以求出 b b b m o d   p mod\ p mod p 下的逆元,然后乘上 a a a,再 m o d   p mod\ p mod p,就是这个分数的值了。

快速幂求逆元

这个做法要利用费马小定理,如下:

p p p 为素数, a a a 为正整数,且 a a a p p p 互质,则有 a p − 1 ≡ 1   ( m o d   p ) a^{p−1} ≡ 1 \ (mod \ p) ap11 (mod p)

可以发现这个式子右边刚好为 1 1 1,因此,代入原式即可得到:

a ∗ x ≡ 1   ( m o d   p ) a ∗ x ≡ 1\ (mod\ p) ax1 (mod p)

a ∗ x ≡ a p − 1   ( m o d   p ) a ∗ x ≡ a^{p−1}\ (mod\ p) axap1 (mod p)

x ≡ a p − 2   ( m o d   p ) x ≡ a^{p−2}\ (mod\ p) xap2 (mod p)

所以我们可以用快速幂来算出 a p − 2   ( m o d   p ) a^{p−2}\ (mod\ p) ap2 (mod p) 的值,这个数就是它的逆元了。

组合数

C a b = a ∗ ( a − 1 ) ∗ . . . ∗ ( a − b + 1 ) b ∗ ( b − 1 ) ∗ . . . ∗ 1 = a ! b ! ∗ ( a − b ) ! C_a^b = \frac{a*(a-1)*...*(a-b+1)}{b*(b-1)*...*1} = \frac{a!}{b!*(a-b)!} Cab=b(b1)...1a(a1)...(ab+1)=b!(ab)!a!

首先,预处理阶乘的余数和阶乘逆元的余数:

f a c t [ i ] = ( i ! )   m o d   ( 1 0 9 + 7 ) fact[i] = (i!)\ mod \ (10^9+7) fact[i]=(i!) mod (109+7)

i n f a c t [ i ] = ( i ! ) − 1   m o d   ( 1 0 9 + 7 ) infact[i] = (i!)^{-1}\ mod\ (10^9+7) infact[i]=(i!)1 mod (109+7)

那么,组合数求解如下:

C a b = f a c t [ a ] ∗ i n f a c t [ b ] ∗ i n f a c t [ a − b ] C_a^{b} = fact[a]*infact[b]*infact[a-b] Cab=fact[a]infact[b]infact[ab]

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long ll;

const int N = 100010, mod = 1e9 + 7;

int fact[N], infact[N];

int qmi(int a, int b, int m)
{
    int res = 1;
    while (b)
    {
        if (b & 1) res = (ll)res * a % mod;
        a = (ll)a * a % mod;
        b >>= 1;
    }
    return res;
}

int main()
{
    // 预处理阶乘的余数和阶乘逆元的余数
    fact[0] = 1, infact[0] = 1;
    for (int i = 1; i < N; i++)
    {
        fact[i] = (ll)fact[i - 1] * i % mod;
        infact[i] = (ll)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
    
    int n;
    scanf("%d", &n);
    
    while (n--)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        printf("%d\n", (ll)fact[a] * infact[b] % mod * infact[a - b] % mod);
    }
    
    return 0;
}

3.卢卡斯定理

题目描述

给定 n n n 组询问,每组询问给定三个整数 a , b , p a,b,p a,b,p,其中 p p p 是质数,请你输出 C a b   m o d   p C_a^b\ mod\ p Cab mod p 的值。

数据范围

1 ≤ n ≤ 20 1 \le n \le 20 1n20

1 ≤ b ≤ a ≤ 1 0 18 1 \le b \le a \le 10^{18} 1ba1018

1 ≤ p ≤ 1 0 5 1 \le p \le 10^5 1p105

Lucas定理

p p p 是质数,则对于任意整数 1 ≤ m ≤ n 1 \leq m \leq n 1mn C n m ≡ C n   m o d   p m   m o d   p ∗ C n / p m / p   ( m o d   p ) C_n^m \equiv C_{n\ mod\ p}^{m\ mod \ p}*C_{n/p}^{m/p}\ (mod\ p) CnmCn mod pm mod pCn/pm/p (mod p)

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long ll;

// 快速幂模板
int qmi(int a, int b, int p)
{
    int res = 1;
    while (b)
    {
        if (b & 1) res = (ll)res * a % p;
        a = (ll)a * a % p;
        b >>= 1;
    }
    return res;
}

// 通过定义求组合数C(a, b)
int C(int a, int b, int p)
{
    if (b > a) return 0;
    
    int res = 1;
    for (int i = 1, j = a; i <= b; i++, j--)
    {
        res = (ll)res * j % p;
        res = (ll)res * qmi(i, p - 2, p) % p;
    }
    return res;
}

int lucas(ll a, ll b, int p)
{
    if (a < p && b < p) return C(a, b, p);
    return (ll)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}

int main()
{
    int n;
    scanf("%d", &n);
    
    while (n--)
    {
        ll a, b;
        int p;
        scanf("%lld%lld%d", &a, &b, &p);
        printf("%d\n", lucas(a, b, p));
    }
    
    return 0;
}

4.将组合数分解质因数+高精度乘低精度

题目描述

输入 a , b a, b a,b,求 C a b C_a^b Cab 的值。注意结果可能很大,需要使用高精度计算。

数据范围

1 ≤ b ≤ a ≤ 5000 1 \le b \le a \le 5000 1ba5000

思路

当我们需要求出组合数的真实值,而非对某个数的余数时,分解质因数的方式比较好用。

C a b = a ∗ ( a − 1 ) ∗ . . . ∗ ( a − b + 1 ) b ∗ ( b − 1 ) ∗ . . . ∗ 1 = a ! b ! ∗ ( a − b ) ! C_a^b = \frac{a*(a-1)*...*(a-b+1)}{b*(b-1)*...*1} = \frac{a!}{b!*(a-b)!} Cab=b(b1)...1a(a1)...(ab+1)=b!(ab)!a!

首先筛选出范围内的所有质数,然后将组合数分解质因数为 p 1 c 1 ∗ p 2 c 2 ∗ . . . ∗ p k c k p_1^{c_1} * p_2^{c_2} * ... * p_k^{c_k} p1c1p2c2...pkck,最后用高精度乘法将所有质因子乘起来即可。

如何求 n ! n! n! 中有多少个质因子 p p p 呢?

⌊ n p ⌋ + ⌊ n p 2 ⌋ + ⌊ n p 3 ⌋ + . . . \lfloor \frac{n}{p} \rfloor+\lfloor \frac{n}{p^2} \rfloor+\lfloor \frac{n}{p^3} \rfloor+... pn+p2n+p3n+...

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 5010;

int primes[N], cnt;
bool st[N];
int sum[N];

// 线性筛
void get_primes(int n)
{
    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] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

// 求n!中有多少个质因子p
int get(int n, int p)
{
    int res = 0;
    while (n)
    {
        res += n / p;
        n /= p;
    }
    return res;
}

// 高精度乘以低精度
vector<int> mul(vector<int> a, int b)
{
    vector<int> c;
    int t = 0;
    for (int i = 0; i < a.size(); i++)
    {
        t += a[i] * b;
        c.push_back(t % 10);
        t /= 10;
    }
    while (t)
    {
        c.push_back(t % 10);
        t /= 10;
    }
    return c;
}

int main()
{
    int a, b;
    scanf("%d%d", &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;
    res.push_back(1);
    
    for (int i = 0; i < cnt; i++)
    {
        for (int j = 0; j < sum[i]; j++)
        {
            res = mul(res, primes[i]);
        }
    }
    
    for (int i = res.size() - 1; i >= 0; i--)
    {
        printf("%d", res[i]);
    }
    
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【模板】组合数取模 的相关文章

  • 将 2D 数组映射到 1D 数组

    我想用一维数组来表示一个二维数组 函数将传递两个索引 x y 和要存储的值 这两个索引代表一维数组的单个元素 并相应地设置它 我知道一维数组需要具有 arrayWidth arrayHeight 的大小 但我不知道如何设置每个元素 例如 如
  • boost线程在中断时不打印退出消息

    我有这段代码用于执行三个线程 其中第二个线程应在按 Enter 时中断并打印退出消息 void input val DO STUFF return void process val DO STUFF try cout lt lt waiti
  • C++ 在 Vector 中使用不可分配的对象

    我想将对象列表存储在std vector 但对象包含引用且无法分配给 但是 我可以复制构造该对象 我能想到的唯一选择是使用指针来包装对象并在需要分配指针时重新设置指针 但这样做的语法会显着降低可读性 特别是在使用迭代器时 我更喜欢另一种选择
  • 组合 Datepicker 和 Timepicker 值 Win 8.1

    我试图同时使用 Datepicker Timepicker 来返回可以存储在数据库中的 DateTime 例如 我想要安排会议的开始日期和结束日期 如果适用 我将如何将这些值组合成 SQL 数据库可以处理的正确格式 任何反馈都会很棒 我让这
  • 防止复制构造和返回值引用的分配

    如果我有一个函数返回对类实例的引用 但我无法控制其源 比如说list
  • 如何检测斑点并将其裁剪成 png 文件?

    我一直在开发一个网络应用程序 我陷入了一个有问题的问题 我会尝试解释我想要做什么 在这里您看到第一个大图像 其中有绿色形状 我想要做的是将这些形状裁剪成不同的 png 文件 并使它们的背景透明 就像大图像下面的示例裁剪图像一样 第一张图像将
  • CMake - 将预构建库链接到 C# 项目

    我正在使用 CMake 构建 C 库 该库依赖于已构建的库 dll 我似乎无法让图书馆链接到我的图书馆 我尝试过使用target link libraries mylib external lib 我也尝试过暴力破解 reference e
  • C#:使用 System.Text 和 System.Text.RegularExpressions 之间的区别

    在 ASP NET C 应用程序中 我注意到为了使用 Regex 和 StringBuilder 我必须将两者都放在 using System Text using System Text RegularExpressions 从简单的角度
  • 推送 Lua 表

    我已经创建了一个Lua表C 但我不知道如何将该表推入堆栈顶部 以便我可以将其传递给 Lua 函数 有谁知道如何做到这一点 这是我当前的代码 lua createtable state libraries size 0 int table i
  • 如何在不使用reinterpret_cast的情况下使用dlsym()加载函数?

    我正在尝试使用 clang tidy 来强制执行 C 核心指南 虽然它确实有很多有效点 但有一件事我无法真正解决 dlsym 返回一个void 我需要以某种方式将其转换为正确的函数指针 为此 我使用reinterpret cast 由于指南
  • 为什么以下代码不允许我使用 fgets 获取用户输入但可以使用 scanf?

    这是一个更大程序的简短摘录 但该程序的其余部分无关紧要 因为我认为我能够隔离该问题 我怀疑这与我使用 fgets 的方式有关 我读过 最好使用 fgets 而不是 scanf 但我似乎无法让它在这里正常工作 当我使用以下代码时 程序不会给我
  • C++ Primer 5th Edition 错误 bool 值没有指定最小大小?

    bool 的最小大小不应该是 1 个字节吗 这有点学术性的东西 尽管它们会转换为数字 并且 与其他所有事物一样 它们最终将基本上由计算机内存中的数字表示 但布尔值不是数字 你的bool可以取值true 或值false 即使您确实需要至少 1
  • 通过 MSBuild 调用 cl.exe 时无限期挂起

    我正在尝试在我的 主要是 C 项目上运行 MSBuild 想象一下一个非常庞大的代码库 Visual Studio 2015 是有问题的工具集 Windows 7 SP1 和 VS 2015 更新 2 即使使用 m 1 从而迫使它仅使用一个
  • 为什么我不能在扩展 List 的类中调用 OrderBy?

    我有一堂课 Deck 其中包含一个名为的方法Shuffle 我正在致力于重构Deck延长List
  • SSBO 是更大的 UBO?

    我目前正在 OpenGL 4 3 中使用 UBO 进行渲染 以将所有常量数据存储在 GPU 上 诸如材料描述 矩阵等内容 它可以工作 但是 UBO 的小尺寸 我的实现为 64kB 迫使我多次切换缓冲区 减慢渲染速度 我正在寻找类似的方法来存
  • 删除对象时指针自动指向空

    假设我有一个对象和其他几个不同类类型的对象中的 10 个指向它的指针 如果对象被删除 这些指针必须设置为空 通常我会将对象的类与具有指向它的指针的类互连 以便它可以通知它们它正在被删除 并且它们可以将它们的指针设置为空 但这也有一个负担 即
  • 有没有办法让 VS2010 在我的方法中扩展或收缩 try 块?

    我的代码有很多 try catch finally 块 与我在 VS2010 中的方法不同 除了添加区域之外 我无法在开发时扩展或收缩这些区域来隐藏内容 try vm R vm Qu vm T vm D vm Fil vm Type vm
  • C++0x 中的新 unicode 字符

    我正在构建一个 API 它允许我获取各种编码的字符串 包括 utf8 utf16 utf32 和 wchar t 根据操作系统 可能是 utf32 或 utf16 新的 C 标准引入了新类型char16 t and char32 t没有这么
  • Windows 上 libcurl 的静态库[重复]

    这个问题在这里已经有答案了 如何将此库 libcurl 静态链接到 exe 我努力了 disable share enable static 没有帮助 我使用的是MingW32 有没有一种简单的方法来静态链接这个库 这样我的应用程序就不再有
  • ASP.NET Core:会话 ID 始终变化

    今天启动了一个全新的 ASP NET Core 网站 按照说明添加会话 我们在索引页上打印出会话 ID 它始终是唯一的 我认为这可能是 cookie 合规性 所以我在 Chrome 的高级设置和调试器中删除了所有 cookie 但横幅不会再

随机推荐

  • 怎么判断ios设备、移动设备、浏览器

    Navigator Navigator接口表示用户代理的状态和标识 允许脚本查询它和注册一些自己的服务 我们可以通过window navigator来访问Navigator对象 常用属性 Navigator appVersion 浏览器版本
  • git-创建release

    git tag a v0 1 1 m Release test git push origin v0 1 1
  • 前端开发微信支付宝支付流程

    微信支付的流程 我认为有几种方案 微信支付 async payOrder 1 创建订单 const orderInfo order price 0 1 consignee addr this addstr goods this cart f
  • 什么是缓冲区?(详细!!!!!干货!!!!!)

    缓冲区 缓冲区其实是不存在的 只不过是我们认为想象出来的 1 把数据写入文件之前 会先写入缓冲区 刷新时才会写入文件内 2 我们所说的缓冲区 实际 只有库函数中存在 3 文件流指针所应用的 文件描述符没有 知识点 1 使用printf向文件
  • 关于Gitlab恼人的Git无权限访问问题解决

    问题 不知什么时候起 从gitlab com上新开的项目中拿代码时 冒出ERROR The project you were looking for could not be found or you don t have permissi
  • docker-compose重新启动Mysql报错changing ownership of ‘/var/lib/mysql/mysql.sock‘: No such file or direct

    一 背景 最近在使用 docker compose 编排整合一个项目 springboot mysql 的时候 首次启动后重新再启动的时候 mysql 容器启动失败 通过 docker logs 命令查看 mysql 容器的启动日志如下 c
  • ajax穿formdata,ajax formdata格式问题

    慕容708150 貌似是因为没有name属性 修改如下 HTML 发布评论JavaScript function postComment var commentForm document getElementById comment for
  • apache转发tomcat http转https

    最近在弄小程序 而小程序网络请求所需要的链接需要https安全链接 之前胡乱配置一番可以用了 不过并不太理解 后来又需要一个php项目 各处查看了一下 需要apache服务器 而我的只有一个域名 已经给了tomcat了 如果在域名后面加端口
  • 2020-10-07

    渗透测试 U盘监控器 1 打开USB监控器 注册时输入任意注册码 出现注册失败页面 2 在Winhex打开USB监控器 exe 文本搜索 注册失败 之后推出字符串文件偏移地址为0x81A79 引用该字符串的指令在字符串地址的常量为0x048
  • Java09

    一 继承 在Java中 使用关键字extends来继承类 父类 public class Fu int num 100 public void methodfu System out println num 子类继承 关键字 public
  • dns服务器项目实例,DNS服务器配置实例-----主DNS服务器

    DNS服务器配置简单实例 主DNS服务器 DNS服务器类型 主DNS服务器 master 辅助DNS服务器 slave 高速缓存服务器 hint 安装bind三部曲 1 查询包是否已经安装 Nborn root 08 06 rpm q bi
  • esp32 Micropython驱动ST7735 1.8寸TFT屏幕 中文显示;时间显示、网络network实时时间获取utptime;urequests、upip等包安装

    参考 https blog csdn net weixin 57604547 article details 122274614 0 线连接 IO就是GPIO引脚 ESP32 TFT 屏ST7735 GND GND 3 3V VDD IO2
  • springboot集成shiro

    这里写自定义目录标题 Springboot集成shiro Shiro介绍 springboot集成shiro Springboot集成shiro Shiro介绍 Shiro是Apache 的一个开源项目 是一个java的安全框架具有认证 授
  • Open Euler学习

    Open Euler学习 目录 Open Euler学习 Open Euler安装截图 使用MobaXterm exe软件 连接自己的操作系统 作业问题 1 使用什么命令查看 ip 地址及接口信息 2 cp和mv命令有什么区别 用什么指令将
  • EM算法推导(收敛性证明和在GMM中的应用)

    一 EM算法的提出 当你有一组数据像如下这样 Note picture source 显然用单个高斯分布模型去拟合它们效果不好 这是一个典型的高斯混合模型的例子 p X
  • TypeError: strptime() takes no keyword arguments ValueError(“‘%s‘ is a bad directive in format ‘%s‘“

    t datetime datetime strptime 2021 5 12 09 28 11 format Y m d h m s 1 错误原因 参数格式不匹配 strptime定义 def strptime data string fo
  • leveldb(六):key的不同种类型

    有5个key的概念 可能会让人混淆 下面就来一个一个的分析 User key 最简单的key了 就是用户传入的数据 Slice user key ParsedInternalKey enum ValueType kTypeDeletion
  • sqlite3交叉编译

    1 交叉编译sqllite3可以先从官网下载最新最新的源码进行编译 sqlite3下载sqlite3有两种版本的源代码 sqlite amalgamation 3300100 zip这种是将所有的操作放到sqlite3中进行使用的 虽然官方
  • 特征筛选1——根据方差筛选(单变量筛选)

    根据给定方差的阈值 删除掉值变化小的维度 以此降低数据规模 当把阈值设置为0的时候 就会删除没有变化的数据 示例 import numpy as np from sklearn feature selection import Varian
  • 【模板】组合数取模

    文章目录 1 利用递推式预处理组合数取模 2 预处理阶乘的余数和阶乘逆元的余数 3 卢卡斯定理 4 将组合数分解质因数 高精度乘低精度 1 利用递推式预处理组合数取模 题目描述 给定 n n n 组询问 每组询问给定两个整数 a