公式
$$C_n^m\%p=C_{n/p}^{m/p}*C_{n\%p}^{m\%p}\%p~~(p為素數)$$
代碼如下
typedef long long ll;
ll mod_pow(ll x, ll n, ll mod)
{
ll res = 1;
while (n > 0)
{
if (n & 1)
res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
ll comb(ll n, ll m, ll p)
{
if (m > n)
return 0;
ll a = 1, b = 1;
m = min(n - m, m);
while(m)
{
a = (a * n--) % p;
b = (b * m--) % p;
}
return a * mod_pow(b, p - 2, p) % p;
}
ll Lucas(ll n, ll m, ll p)
{
if (m == 0)
return 1;
return comb(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
例題
解析:m個相同的豆子,放到n個不同的樹里,有多少種方法。有$C_{n+m}^m$種。具體詳解請看下面的擴展中的插板法。
代碼如下:
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll mod_pow(ll x, ll n, ll mod)
{
ll res = 1;
while (n > 0)
{
if (n & 1)
res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
ll comb(ll n, ll m, ll p)
{
if (m > n)
return 0;
ll a = 1, b = 1;
m = min(n - m, m);
while(m)
{
a = (a * n--) % p;
b = (b * m--) % p;
}
return a * mod_pow(b, p - 2, p) % p;
}
ll Lucas(ll n, ll m, ll p)
{
if (m == 0)
return 1;
return comb(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
int main(int argc, char* argv[])
{
ios::sync_with_stdio(false);
cin.tie(0);
ll T, n, m, p;
cin >> T;
while (T--)
{
cin >> n >> m >> p;
cout << Lucas(n + m, m, p) << endl;
}
return 0;
}
擴展
插板法
適用類型
一組相同的元素,分成若干不同的組,每組至少一個元素。
例題1
將8個相同的小球放到3個不同的盒子,每個盒子至少放一個球,一共有多少種方法。
解:8個盒子,有7個空,分到3個盒子,需要插2塊板,$C_7^2=21$種。
對於不滿足 每組至少一個元素條件的,應該先 轉化為標准形式。
例題2
將8個相同的小球放到3個不同的盒子,每個盒子至少放兩個球,一共有多少種方法。
解析:先往每一個盒子里放一個小球。轉化為:5個相同的小球放到不同的盒子,每個盒子至少放1個小球,一共有多少種方法。$C_4^2=6$種。
例題3
將8個相同的小球放到3個不同的盒子,有多少種方法。
解析:我們先讓每個盒子吐出1個球,使得每個盒子至少一個球,分球的時候再讓盒子吃回去。轉化為:11個相同的球放到3個不同的盒子中,每個盒子至少一個,有多少種方法。$C_{10}^2=45$種。
例題4
$a+b+c=10$有多少組正整數解。
解析:轉化為:10個相同的小球,放到不同的3個盒子中,每個盒子至少一個,有多少方法。$C_9^2=36$種。
例題5
$a+b+c=10$有多少組非負整數解。
解析:轉化為:13個相同的小球,放到不同的3個盒子中,有多少方法。$C_{12}^2=66$種。
例題6
$a+b+c\leqslant 10$有多少組非負整數解。
解析1:轉化為$a+b+c+d =10$,即10個相同的球,放到4個不同的盒子中,有多少方法。$C_{13}^3=286$種。
解析2:列舉所有情況:$a+b+c=0(C_2^2)$,$a+b+c=1(C_3^2)$,$\cdots$,$a+b+c=10(C_{12}^2)$,$\sum\limits_{i=2}^{12}C_i^2=C_{13}^3=286$種。
注:$\sum\limits_{i=m}^nC_i^m=C_{n+1}^{m+1}$。
楊輝三角性質之一:斜線上數字的和等於其向左(從左上方到右下方的斜線)或向右拐彎(從右上方到左下方的斜線),拐角上的數字。