逆元線性打表後求大組合數(m 10 6)

2021-10-01 10:39:00 字數 1590 閱讀 5245

逆元求組合數中作用就是講公式中的除法取餘轉化為乘法取餘,其實當m≤10^5時,都可以直接暴力求分子中每個因子的逆元(會用到快速冪),這裡需要先求出p的尤拉函式值。 此處n,p的值在資料範圍(10^18)內就行

除了上面的思路,我們也可以o(n)打表得出1!~n!的逆元對p取模後的結果:求逆元的方法總結、打表,這時就不需要用到快速冪求逆元,但此時對n的範圍就有要求了:n≤10^6, m≤10^6

打表**實現:

注意:需要滿足條件n[1]

=1;for

(int i=

2;i<=n;

++i)

inv[i]

=p-p/i*inv[p%i]

%p;for

(int i=

2;i<=n;

++i)

inv[i]

=(inv[i]

*inv[i-1]

)%p;例題1:p3807 【模板】盧卡斯定理

**:

#include

#include

#include

#include

#define mod 1000000007

#include

using namespace std;

typedef

long

long ll;

const

int manx=

2e5+7;

ll a[manx]

,b[manx]

;ll lucas

(ll n,ll m,ll p)

intmain()

}

因為這裡n+m可能會大於p,所以需要用盧卡斯轉化一下。

例題2:power-oj2816: alice的程式設計之旅

輸入包含t(1≤t≤106)組資料。

接下來t行,每行包含兩個正整數n,m。(1≤m≤n≤105)

用上面的方法,可以先將1~n的階乘階乘的逆元打表後,o(1)得到結果:

#include

#include

#include

#include

#include

using namespace std;

typedef

unsigned

long

long ll;

const ll manx=

1e5+10;

const ll p=

1e9+7;

ll inv[manx]

,a[manx]

;int

main()

scanf

("%d"

,&t)

;while

(t--

)return0;

}

線性求逆元

在某些組合數的計數問題中,經常會用到逆元,這裡我們講一下如何線性求出1到n在模p意義下的逆元,注意p為質數。假設我們當前要求a在模p意義下的逆元。令p ak r,0 rp a k r,0 r 那麼 ak r 0 modp a k r 0 modp 然後恒等式變形,兩邊同時乘a 1 r 1 a 1 r...

線性求逆元

求逆元可以用費馬小定理或者擴充套件歐幾里得,也可以用如下的o n 演算法 背下來 這個對p是有要求的,p 也就是模數 必須是質數 p不是質數的話,就用擴充套件歐幾里得比較方便了 兩個數有逆元當且僅當互質!inv 1 1 for i 2 i p i inv i p p i inv p i p也可以用另...

線性求逆元及其過程

連續兩天考了求逆元。所以想著寫一篇關於線性求逆元的部落格。inv 1 1 for int i 2 i n i inv i mod long long mod i inv mod i mod 我們要求i在模p意義下的逆元inv i 那麼我們就設ki r p,所以ki r移項可以得到 r 兩邊同時除以i...