C 求組合數 再取模

2021-10-06 05:25:03 字數 1358 閱讀 4375

c(n,m) = n!/(n-m)!m!

c++在處理大數除法的時候好像會出現問題,所以用除法有時候會因為精度不夠沒法得到正確答案.需要把除法變成乘法.

知識儲備:①逆元②快速冪

逆元:若a*x%m=1 我們稱x是a的逆元,x寫做a-1(相當於整除中的倒數),那假設我們要求a/b%m的值,當b特別大時我們無法得到正確答案,這時候對式子進行一些操作:

a / b % m = a / b * 1 % m = a / b * (b * b-1) % m --------------------- (b * b-1 % m = 1)

= a * b-1 % m

這時候只要求出b-1的值就可以求出a/b%m的值了.

怎樣求乙個數的逆元呢?

首先,要求乙個數的逆元,需要兩個元素,乙個是這個數,另乙個是模數.

a * a-1%m=1 若m是質數,根據費馬小定理a-1 = am-2 具體解釋可以在網上搜到.am-2就要用到快速冪了.

既然會求逆元了,怎麼求階乘的逆元呢?

①可以用線性演算法將1~n的所有逆元都求出來,設inv[i]是i的逆元.有性質:

inv[i] = (m- m/i) * inv[m%i] % m

然後將每個inv[i]乘起來就是i!的階乘的逆元

inv[1]

=1;for

(int i =

2;i <= n;i++

) inv[i]

=(m-m/i)

*inv[m % i]

%m;for

(int i =

1;i <= n;i++

) inv[i]

= inv[i-1]

*inv[i]

%m ;

②可以從後往前倒推

若n!的逆元=k,那麼n-1!的逆元=kn

n! * k %m=1

n-1!=n!/n

n!/n * kn = 1

所以n-1!的逆元等於k*n

這種演算法首先求出i!,再求出n!的逆元.在倒推出i!的逆元

fac[1]

=1;for

(int i =

2;i<=n;i++

) fac[i]

=fac[i-1]

*i%m;

inv[n]

=quick_sort

(fac[n]

,m-2);

//根據費馬小定理

for(

int i = n-

1;i>=

1;i--

)inv[i]

= inv[i+1]

*(i+1)

%m;

組合數求模

大家都在中學階段學習了組合數的定義 這個表示的是從n個元素中選取m個元素的方案數。ps.組合數求模似乎只用在資訊學競賽和 acm競賽等計算機程式設計設計大賽中 求在現實中的運用 可以知道當n,m取得比較大的時候,組合數可能很大很大 天文數字?無法度量?例如 c 100,50 100891344545...

知識精華 組合數求模

大家都在中學階段學習了組合數的定義 這個表示的是從n個元素中選取m個元素的方案數。ps.組合數求模似乎只用在資訊學競賽和 acm競賽等計算機程式設計設計大賽中 求在現實中的運用 可以知道當n,m 取得比較大的時候,組合數可能很大很大 天文數字?無法度量?例如 c 100,50 10089134454...

組合數學 求組合數

對於求組合數,要根據所給資料範圍來選擇合適的演算法 這道題中所給的資料範圍適合用打表的方法直接暴力求解 先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可 include using namespace std const int n 2010 const int mod 1e9 ...