逆元求組合數中作用就是講公式中的除法取餘轉化為乘法取餘,其實當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...