求組合數C n,m 的三種方法

2021-10-10 08:19:46 字數 1396 閱讀 2359

一.暴力法

複雜度o(n)

適用:小資料,n=60可用

**:

f[0]

[0]=

1;for(

int i=

1;i<=n;i++

)for

(int j=

0;j<=i;j++)if

(j) f[i]

[j]=f[i-1]

[j]+f[i-1]

[j-1];

else f[i]

[j]=f[i-1]

[j];

二.逆元法

複雜度o(nlog(n))

適用:m小於p;

思路:把除以乙個數變成乘乙個數的逆元。

逆元求法

【對於正整數a和p,如果有ax≡1(mod p),那麼把這個同餘方程中x的小正整數解叫做a的逆元。由費馬小定理知,當a與p互質時,a^(p-1) %p=1。所以當p是質數時,a的逆元為a^(p-2)。】

**:1)只需求一次大組合數時可使用

ll power

(ll a,ll b)

return ans%mod;

}ll c

(ll n,ll m)

ll ans=1;

n=min(n,m-n)

;for

(ll i=

1;i<=n;i++

)for

(ll i=m-n+

1;i<=m;i++

)return ans;

}

2)求多次,優化一下,預處理階乘和階乘的逆元

ll f[n]

,inv[n]

;ll pow_mod

(ll a,ll b,ll c)

return ans%c;

}inline ll c

(int k,

int n)

void

init()

inv[n-1]

=pow_mod

(f[n-1]

,mod-

2,mod)

;//逆推預處理階乘的逆元

for(

int i = n-

2; i >=

0; i--

)return

;}

三.lucas定理

複雜度:o(n*log(n)*log(n/mod))

適用:m>p,m,n很大時

盧卡斯(lucas)定理的定義

再運用秦九韶演算法可求得ai,bi;

**:

ll lucas

(ll a,ll b)

配合逆元法使用即可

組合數 求組合數的幾種方法總結

求c n,m mod的方法總結 1.當n,m都很小的時候可以利用楊輝三角直接求。c n,m c n 1,m c n 1,m 1 2.利用乘法逆元。乘法逆元 a b mod a b mod 2 mod為素數。逆元可以利用擴充套件歐幾里德或尤拉函式求得 1 擴充套件歐幾里德 b x p y 1 有解,x...

求素數的三種方法

具體篩法是 先把n個自然數按次序排列起來。1不是質數,也不是合數,要划去。第二個數2是質數留下來,而把2後面所有能被2整除的數都劃去。2後面第乙個沒劃去的數是3,把3留下,再把3後面所有能被3整除的數都劃去。3後面第乙個沒劃去的數是5,把5留下,再把5後面所有能被5整除的數都劃去。這樣一直做下去,就...

求Fibonacci數列的三種方法

fibonacci數列 0,1,1,2,3,5,8,13。第一招 遞推法 includeint f 47 int main 第二招 不斷變換初始 include int main if n 1 n 2 puts 1 else if n 0 puts 0 else printf d n f3 retu...