数论 · Lucas 定理
前言
在 A 了 Lucas 模板之后,十几天才弄懂证明。
UPDATE
-
2021 - 12 - 25:学习了 exLucas
详见 数论 · exLucas 定理
定理
组合数取模
对于整数
简而言之就是把
有
证明
先提出一个用二项式定理证的一个柿子
都要看烂了,就不证了。
根据
再结合最上面的柿子,就有
然后我们考虑左边的柿子,其中
又
所以在右边的每一个括号的次数
这样就得到了
按照这个柿子,我们就可以递归求解
证毕!
代码
其中,
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rint register int
const int maxn = 1e5 + 5;
int T, n, m, p;
int a[maxn];
inline int read ()
{
int x = 1, s = 0;
char ch = getchar ();
while (ch < '0' or ch > '9') {if (ch == '-') x = -1; ch = getchar ();}
while (ch >= '0' and ch <= '9') s = s * 10 + ch - '0', ch = getchar ();
return s * x;
}
inline int pow (int x, int t)
{
int res = 1;
x %= p;
while (t >= 1)
{
if (t & 1)
res = res * x % p, t -= 1;
t /= 2, x = x * x % p;
}
return res;
}
inline int inv (int x)
{
return pow (x, p - 2);
}
inline int cm (int n, int m)
{
if (m > n) return 0;
return ((a[n] * inv (a[m])) % p * inv (a[n - m]) % p);
}
inline int lucas (int a, int b)
{
if (!b) return 1;
return cm (a % p, b % p) * lucas (a / p, b / p) % p;
}
signed main ()
{
a[0] = 1;
T = read ();
while (T--)
{
n = read (), m = read (), p = read ();
for (rint i (1); i <= p; ++i)
a[i] = a[i - 1] * i % p;
printf ("%lld\n", lucas (n + m, n));
}
return 0;
}
——