利用逆元,当n和m很大,mod比较小的时候使用
C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p,递归
const int N = 100000 + 5; LL mul(LL a, LL b, LL p) {//快速乘,计算a*b%p LL ret = 0; while(b) { if(b & 1) { ret = (ret + a) % p; } a = (a + a) % p; b >>= 1; } return ret; } LL fact(int n, LL p) {//n的阶乘求余p LL ret = 1; for (int i = 1; i <= n ; i ++) { ret = ret * i % p ; } return ret ; } void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d) { if (!b) { d = a, x = 1, y = 0; } else { ex_gcd(b, a % b, y, x, d); y -= x * (a / b); } } LL inv(LL t, LL p) {//如果不存在,返回-1 LL d, x, y; ex_gcd(t, p, x, y, d); return d == 1 ? (x % p + p) % p : -1; } LL comb(int n, int m, LL p) {//C(n, m) % p if (m < 0 || m > n) { return 0; } return fact(n, p) * inv(fact(m, p), p) % p * inv(fact(n-m, p), p) % p; } LL Lucas(LL n, LL m, int p) { return m ? Lucas(n/p, m/p, p) * comb(n%p, m%p, p) % p : 1; }需要注意一点,在乘法中,如果有可能爆long long记得用快速乘取模,防止爆精度