數論4 組合數

目錄

前言

求法一

代碼

求法二

代碼

求法三

代碼

求法四

代碼


前言

今天要將最后一部分,主要涉及組合數的四種求法。

前置知識

組合數的通項公式:
C_n^m = n! / {m!(n-m)!}

組合數的遞推公式:

C_n^m = C_{n-1}^m + C_{n - 1} ^{m - 1}

盧卡斯定理:
C_n^m = C_{n\%p}^{m\%p} * C_{n/p}^{m/p}

我們今天需要求的四種求法主要基于這幾個公式。


求法一

求法一利用的是遞推公式,主要用于n <= 2000即可以打n^2的表的題目。

這個遞推公式是怎樣求出來的呢?其實很簡單,我們單獨對一個元素做分類討論,顯然有兩種可能的情況:

  • 選擇:C_{n - 1}^{m - 1}

  • 不選擇:C_{n - 1} ^ {m}

最后二者相加能夠得到的就是C_n^m,時間復雜度是O(n^2)


代碼

const int N = 2010;
int C[N][N];
?
void init()
{for (int i = 0; i < N; i++){C[i][0] = 1; for (int j = 1; j <= i; j++)C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % P;}
}

求法二

求法二主要應對的是n <= 1e5這種只能夠打一維表的數據。我們使用通項公式求解。不過需要取模,而對于模意義下顯然不可以直接做除法,需要求逆元

注意這里有個隱藏條件是P是質數,這樣才能保證每一項都存在逆元。時間復雜度為O(nlogn)


代碼

const int N = 100010, P = 10007;
int F[N], Fe[N];
?
int quick(int n, int k)
{int cnt = 1;while (k){if (k & 1) cnt = cnt * n % P;n = n * n % P;k >>= 1;}return cnt;
}
?
void init()
{F[0] = Fe[0] = 1;for (int i = 1; i < N; i++){F[i] = F[i - 1] * i % P;Fe[i] = Fe[i - 1] * quick(i, P - 2) % P;}
}

求法三

可算是找到了一道模板題(

這道題可以發現n很大,若再使用階乘求得話時間復雜度就是nlogn是必定超時的。

對于這種情況我們就可以使用盧卡斯定理求解,當然依舊有個前提是P是質數

至于這個盧卡斯定理怎么求出來的我也不太懂,大家記住就好了,很形象,不難記。

若使用盧卡斯定理的話時間復雜度是:
log_p^n * p * log^p


代碼

#include<iostream>
using namespace std;
const int P = 10007;
int t, m, n;
?
int quick(int n, int k)
{int cnt = 1;while(k){if(k & 1) cnt = cnt * n % P;k >>= 1;n = n * n % P;}return cnt;
}
?
int C(int n, int m)
{int l = 1;for(int i = 1, j = n; i <= m; i++, j--){l = l * j % P;l = l * quick(i, P - 2) % P; //乘以逆元}return l;
}
?
int lks(int n, int m)
{if(n < P) return C(n, m);return C(n % P, m % P) * lks(n/P, m/P) % P;
}
?
int main()
{scanf("%d", &t);while(t--){scanf("%d%d", &n, &m);printf("%d\n", lks(n, m));}}

求法四

n很大并且不取余

顯然對于這樣的問題就需要使用高精度來求解。

我們使用的依舊是通項公式

不過對于通項公式:C_n^m = n! / {m!(n-m)!}

里面是有乘法有除法的,這并不理想,有沒有更優秀的求法呢?

這個求法很巧妙的,原理就是將階乘分解質因數,然后消掉重復的部分,因為組合數都是整數所以上面部分是一定可以被下面部分整除的,所以大家不需要考慮消不完的情況。

那么我們如何對階乘分解質因數呢?這個很簡單,我們首先篩出所1~n中所有的質數,隨后運用一個公式:
c = n/p + n/p^2 + n/p^3 + ...

對于這個公式主播最開始感覺有些摸不著頭腦,但是想明白后只想說:妙,太妙了……

如何來理解呢?其實很簡單n/p其實就是求出1 ~ n中能p整除的數字的個數,以此類推……


代碼

#include<iostream>
#include<vector>
//#define int long long
using namespace std;
//typedef long long LL;
const int N = 1e6 + 10;
bool is_prime[N];
int n, m;
?
int quick(int n, int k)
{int l = 1;while (k){if (k & 1) l *= n;n = n * n;k >>= 1;}//printf("%d\n", l);return l;
}
?
vector<int> prime_shai(int n) //線性篩法
{vector<int> p;for (int i = 2; i <= n; i++){if (!is_prime[i]) p.push_back(i);for (int j = 0; p[j] <= n / i; j++){is_prime[i * p[j]] = true;if (i % p[j] == 0) break;}}return p;
}
?
int get_num(int n, int p)
{int l = 0;int cnt = p;while (n / p){l += n / p;p *= cnt;}return l;
}
?
vector<int> cur(vector<int>& A, int b)
{int x = 0;vector<int> C;for (int i = 0; i < A.size(); i++){x += A[i] * b;C.push_back(x % 10);x /= 10;}while (x){C.push_back(x % 10);x /= 10;}return C;
}
?
int main()
{scanf("%d%d", &n, &m);vector<int> A = { 1 }; //高精度vector<int> p = prime_shai(n);for (int i = 0; i < p.size(); i++){int l = get_num(n, p[i]) - get_num(m, p[i]) - get_num(n - m, p[i]);A = cur(A, quick(p[i], l));}for (int i = A.size() - 1; i >= 0; i--)printf("%d", A[i]);return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900171.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

構建自己的私有 Git 服務器:基于 Gitea 的輕量化部署實戰指南

對于個人開發者、小型團隊乃至企業來說&#xff0c;將項目代碼托管在 GitHub、Gitee 等公共平臺雖然方便&#xff0c;但也存在一定的隱私與可控性問題。 搭建一套私有 Git 代碼倉庫系統&#xff0c;可以實現對源碼的完全控制&#xff0c;同時不依賴任何第三方平臺&#xff0c;…

Linux操作系統 4.Linux實用操作

一、各類小技巧&#xff08;快捷鍵&#xff09; 1.CTRL C 強制停止 1.Linux某些程序的運行&#xff0c;如果想要強行停止它&#xff0c;可以使用ctrlc 2.命令輸入錯誤&#xff0c;也可以通過快捷鍵ctrl c,退出當前輸入&#xff0c;重新輸入&#xff0c;或者ctrlc跳過當前這…

react redux的學習,單個reducer

redux系列文章目錄 一 什么redux&#xff1f; redux是一個專門用于做狀態管理的JS庫(不是react插件庫)。它可以用在react, angular, vue等項目中, 但基本與react配合使用。集中式管理react應用中多個組件共享的狀 簡單來說&#xff0c;就是存儲頁面的狀態值的一個庫&#xf…

PCI與PCIe接口的通信架構是主從模式嗎?

PCI&#xff08;Peripheral Component Interconnect&#xff09;總線在通信架構上本質是主從模式&#xff0c;但其具體實現和角色分配在不同版本&#xff08;如傳統PCI與PCI Express&#xff09;中存在差異。以下是詳細分析&#xff1a; 傳統PCI總線的主從模式 (1) 基本架構 主…

java項目掛機自動重啟操作指南

前段時間有個伙伴問我&#xff0c;java項目掛機怎么自動重啟。。。。。。今天就寫一個 .sh腳本來實現應用掛機的自動重啟功能 #!/bin/bash # 查詢mita的進程個數 countps -ef | grep mita.jar | grep -v "grep" | wc -l # echo $count nowtimedate "%Y-%m-%d %H…

開放最短路徑優先 - OSPF【LSA詳細】

目錄 LSA的頭部結構 LSA類型 LSA數據包 LSA的主要作用是傳遞路由信息。 LSA的頭部結構 共占20個字節&#xff0c;不同類型的LSA頭部字段部分都是相同的。 鏈路狀態老化時間(Link-State Age) 2個字節。指示該條LSA的老化時間&#xff0c;即它存在了多長時間&#xff0c;單位…

SpringBoot+Spring+MyBatis相關知識點

目錄 一、相關概念 1.spring框架 2.springcloud 3.SpringBoot項目 4.注解 5.SpringBoot的文件結構 6.啟動類原理 二、相關操作 1.Jar方式打包 2.自定義返回的業務狀態碼 3.Jackson 4.加載配置文件 5.異常處理 三、優化配置 1.簡化sql語句 2.查詢操作 復雜查詢 一…

《雙影奇境》手機版上線?ToDesk用跨平臺技術實現「全設備云電腦3A游戲」

《雙影奇境》是由Hazelight Studios研發發行的一款雙人合作冒險類游戲&#xff0c;玩家們在游戲中將扮演米歐和佐伊兩位風格迥異的女作家&#xff0c;劇情講述的是她們被騙進入一臺意在竊取創意的機器后便陷入了自己創作的故事之中&#xff0c;并且必須相互依靠&#xff0c;努力…

【教程】Windows下 Xshell 連接跳板機和開發機

需求 使用遠程連接工具 Xshell 連接跳板機&#xff0c;再從跳板機連接開發機&#xff0c;用戶登陸方式為使用密鑰。 方法 首先&#xff0c;建立一個會話&#xff0c;用于配置跳板機信息和開發機轉跳信息&#xff1a; 在【連接】頁面&#xff0c;給跳板機取個名字&#xff0c…

如何快速入門物聯網單片機開發?

背景 物聯網單片機硬件開發涉及多個階段&#xff0c;元器件是否“自己設計”取決于具體需求。以下是詳細解答和學習方案&#xff1a; 一、元器件是否自己設計&#xff1f; 通用元器件&#xff1a; 大多數情況下&#xff0c;開發者直接使用現成的標準化元器件&#xff08;如電阻…

每日一題(小白)模擬娛樂篇11

由題可知就是要求計算一個數字&#xff0c;可以整除10進制的每一位&#xff0c;亦可以整除8進制和16進制的每一位。要求找出第2023個能夠在三個進制下同時被10進制整除的數字。 Java中已經封裝了進制轉換的方法&#xff0c;以下是一些常用的轉換方法&#xff1a;&#x1f447;…

阿里巴巴langengine二次開發大模型平臺

阿里巴巴LangEngine開源了&#xff01;支撐億級網關規模的高可用Java原生AI應用開發框架 - Leepy - 博客園 阿里國際AI應用搭建平臺建設之路(上) - 框架篇 基于java二次開發 目前Spring ai、spring ai alibaba 都是java版本的二次基礎能力 重要的是前端工作流 如何與 服務端的…

MINIQMT學習課程Day8

獲取qmt賬號的資金賬號后&#xff0c;我們進入下一步&#xff0c;如何獲得當前賬號的持倉情況 還是之前的步驟&#xff0c;打開qmt&#xff0c;選擇獨立交易&#xff0c; 之后使用pycharm&#xff0c;編寫py文件。 from xtquant import xtdata from xtquant.xttrader import…

在QGIS中將矢量數據導出為JSON

在QGIS中將矢量數據導出為JSON的完整操作指南如下&#xff0c;支持GeoJSON標準格式及自定義配置&#xff1a; 一、標準GeoJSON導出&#xff08;推薦&#xff09; 適用場景&#xff1a;生成符合OGC標準的地理JSON文件&#xff0c;適用于Web地圖開發 準備圖層 確保目標圖層在QG…

Netty——連接超時 與 斷開重連

文章目錄 1. 處理連接超時和斷開重連的原因2. 處理連接超時和斷開重連的方法2.1 處理連接超時2.1.1 步驟一&#xff1a;配置連接超時時間2.1.2 步驟二&#xff1a;監聽連接結果 2.2 處理斷開重連2.2.1 步驟一&#xff1a;監聽連接斷開事件2.2.2 步驟二&#xff1a;實現重連邏輯…

Redis 與 AI:從緩存到智能搜索的融合之路

Redis 與 AI&#xff1a;從緩存到智能搜索的融合之路 在當今數字化時代&#xff0c;Redis 不僅是一個高性能的緩存系統&#xff0c;更是一個強大的 AI 支持平臺。Redis 通過其向量數據庫功能和 AI 工具&#xff0c;為現代應用提供了獨特的技術優勢。 一、Redis 的 AI 能力 &…

LeetCode435 -- 預定會議問題

0. ref 參考自 1. 題目描述 預定會議問題&#xff1a;給定我們一堆區間&#xff0c;區間不能重疊&#xff08; [ 1 , 2 ] [1,2] [1,2] 和 [ 2 , 3 ] [2,3] [2,3] 的 2 2 2 不算重疊&#xff09;&#xff0c;求最多能保留多少個區間&#xff1f; 做法&#xff1a;貪心&#…

leetcode51-N皇后

leetcode 51 思路 本題可以使用回溯算法來解決。回溯算法通過嘗試所有可能的解決方案來找到問題的解的算法&#xff0c;當發現當前的選擇無法得到有效的解決方案時&#xff0c;就回溯到上一步&#xff0c;嘗試其他的選擇。對于 N 皇后問題&#xff0c;我們可以逐行放置皇后&…

linux paste 命令

paste 是 Linux 中一個用于水平合并文件內容的命令行工具&#xff0c;它將多個文件的對應行以并行方式拼接&#xff0c;默認用制表符&#xff08;Tab&#xff09;分隔。 1. 基本語法 paste [選項] 文件1 文件2 ... 2. 常用選項 選項說明-d指定拼接后的分隔符&#xff08;默…

Linux 入門:基礎開發工具(上)vim,gcc/g++,make/makefile

目錄 一.軟件包管理器 一&#xff09;.軟件包 二&#xff09;.安裝軟件 三&#xff09;.刪除軟件 二.編輯器vim 一&#xff09;.vim的基本介紹 1.正常/普通/命令模式(Normal mode) 2.插入模式(Insert mode) 3.底行模式(last line mode) 二&#xff09;.vim的基本操作 …